mirror of
https://github.com/MariaDB/server.git
synced 2025-04-18 21:44:20 +03:00
MDEV-35000 preparation: Clean up dict_table_t::stat
innodb_stats_transient_sample_pages, innodb_stats_persistent_sample_pages: Change the type to UNSIGNED, because the number of pages in a table is limited to 32 bits by the InnoDB file format. btr_get_size_and_reserved(), fseg_get_n_frag_pages(), fseg_n_reserved_pages_low(), fseg_n_reserved_pages(): Return uint32_t. The file format limits page numbers to 32 bits. dict_table_t::stat: An Atomic_relaxed<uint32_t> that combines a number of metadata fields. innodb_copy_stat_flags(): Copy the statistics flags from TABLE_SHARE or HA_CREATE_INFO. dict_table_t::stats_initialized(), dict_table_t::stats_is_persistent(): Accessors to dict_table_t::stat. Reviewed by: Thirunarayanan Balathandayuthapani
This commit is contained in:
parent
1965b2be16
commit
1ed09cfdcb
@ -1571,10 +1571,10 @@ VARIABLE_NAME INNODB_STATS_PERSISTENT_SAMPLE_PAGES
|
||||
SESSION_VALUE NULL
|
||||
DEFAULT_VALUE 20
|
||||
VARIABLE_SCOPE GLOBAL
|
||||
VARIABLE_TYPE BIGINT UNSIGNED
|
||||
VARIABLE_TYPE INT UNSIGNED
|
||||
VARIABLE_COMMENT The number of leaf index pages to sample when calculating persistent statistics (by ANALYZE, default 20)
|
||||
NUMERIC_MIN_VALUE 1
|
||||
NUMERIC_MAX_VALUE 18446744073709551615
|
||||
NUMERIC_MAX_VALUE 4294967295
|
||||
NUMERIC_BLOCK_SIZE 0
|
||||
ENUM_VALUE_LIST NULL
|
||||
READ_ONLY NO
|
||||
@ -1595,10 +1595,10 @@ VARIABLE_NAME INNODB_STATS_TRANSIENT_SAMPLE_PAGES
|
||||
SESSION_VALUE NULL
|
||||
DEFAULT_VALUE 8
|
||||
VARIABLE_SCOPE GLOBAL
|
||||
VARIABLE_TYPE BIGINT UNSIGNED
|
||||
VARIABLE_TYPE INT UNSIGNED
|
||||
VARIABLE_COMMENT The number of leaf index pages to sample when calculating transient statistics (if persistent statistics are not used, default 8)
|
||||
NUMERIC_MIN_VALUE 1
|
||||
NUMERIC_MAX_VALUE 18446744073709551615
|
||||
NUMERIC_MAX_VALUE 4294967295
|
||||
NUMERIC_BLOCK_SIZE 0
|
||||
ENUM_VALUE_LIST NULL
|
||||
READ_ONLY NO
|
||||
|
@ -284,18 +284,18 @@ release_and_exit:
|
||||
|
||||
/**************************************************************//**
|
||||
Gets the number of reserved and used pages in a B-tree.
|
||||
@return number of pages reserved, or ULINT_UNDEFINED if the index
|
||||
is unavailable */
|
||||
@return number of pages reserved
|
||||
@retval 0 if the index is unavailable */
|
||||
static
|
||||
ulint
|
||||
uint32_t
|
||||
btr_get_size_and_reserved(
|
||||
dict_index_t* index, /*!< in: index */
|
||||
ulint flag, /*!< in: BTR_N_LEAF_PAGES or BTR_TOTAL_SIZE */
|
||||
ulint* used, /*!< out: number of pages used (<= reserved) */
|
||||
uint32_t* used, /*!< out: number of pages used (<= reserved) */
|
||||
mtr_t* mtr) /*!< in/out: mini-transaction where index
|
||||
is s-latched */
|
||||
{
|
||||
ulint dummy;
|
||||
uint32_t dummy;
|
||||
|
||||
ut_ad(mtr->memo_contains(index->lock, MTR_MEMO_SX_LOCK));
|
||||
ut_a(flag == BTR_N_LEAF_PAGES || flag == BTR_TOTAL_SIZE);
|
||||
@ -304,19 +304,19 @@ btr_get_size_and_reserved(
|
||||
|| dict_index_is_online_ddl(index)
|
||||
|| !index->is_committed()
|
||||
|| !index->table->space) {
|
||||
return(ULINT_UNDEFINED);
|
||||
return 0;
|
||||
}
|
||||
|
||||
dberr_t err;
|
||||
buf_block_t* root = btr_root_block_get(index, RW_SX_LATCH, mtr, &err);
|
||||
*used = 0;
|
||||
if (!root) {
|
||||
return ULINT_UNDEFINED;
|
||||
return 0;
|
||||
}
|
||||
|
||||
mtr->x_lock_space(index->table->space);
|
||||
|
||||
ulint n = fseg_n_reserved_pages(*root, PAGE_HEADER + PAGE_BTR_SEG_LEAF
|
||||
auto n = fseg_n_reserved_pages(*root, PAGE_HEADER + PAGE_BTR_SEG_LEAF
|
||||
+ root->page.frame, used, mtr);
|
||||
if (flag == BTR_TOTAL_SIZE) {
|
||||
n += fseg_n_reserved_pages(*root,
|
||||
@ -343,14 +343,14 @@ dict_stats_save_defrag_stats(
|
||||
|
||||
const time_t now= time(nullptr);
|
||||
mtr_t mtr;
|
||||
ulint n_leaf_pages;
|
||||
uint32_t n_leaf_pages;
|
||||
mtr.start();
|
||||
mtr_sx_lock_index(index, &mtr);
|
||||
ulint n_leaf_reserved= btr_get_size_and_reserved(index, BTR_N_LEAF_PAGES,
|
||||
&n_leaf_pages, &mtr);
|
||||
uint32_t n_leaf_reserved= btr_get_size_and_reserved(index, BTR_N_LEAF_PAGES,
|
||||
&n_leaf_pages, &mtr);
|
||||
mtr.commit();
|
||||
|
||||
if (n_leaf_reserved == ULINT_UNDEFINED)
|
||||
if (!n_leaf_reserved)
|
||||
return DB_SUCCESS;
|
||||
|
||||
THD *thd= current_thd;
|
||||
|
@ -198,8 +198,7 @@ dict_tables_have_same_db(
|
||||
/** Decrement the count of open handles */
|
||||
void dict_table_close(dict_table_t *table)
|
||||
{
|
||||
if (table->get_ref_count() == 1 &&
|
||||
dict_stats_is_persistent_enabled(table) &&
|
||||
if (table->get_ref_count() == 1 && table->stats_is_persistent() &&
|
||||
strchr(table->name.m_name, '/'))
|
||||
{
|
||||
/* It looks like we are closing the last handle. The user could
|
||||
@ -238,7 +237,7 @@ dict_table_close(
|
||||
dict_table_close(table);
|
||||
else
|
||||
{
|
||||
if (table->release() && dict_stats_is_persistent_enabled(table) &&
|
||||
if (table->release() && table->stats_is_persistent() &&
|
||||
strchr(table->name.m_name, '/'))
|
||||
{
|
||||
/* Force persistent stats re-read upon next open of the table so
|
||||
|
@ -599,7 +599,7 @@ void dict_stats_empty_table(
|
||||
table->stat_clustered_index_size = 1;
|
||||
/* 1 page for each index, not counting the clustered */
|
||||
table->stat_sum_of_other_index_sizes
|
||||
= UT_LIST_GET_LEN(table->indexes) - 1;
|
||||
= uint32_t(UT_LIST_GET_LEN(table->indexes) - 1);
|
||||
table->stat_modified_counter = 0;
|
||||
|
||||
dict_index_t* index;
|
||||
@ -617,7 +617,7 @@ void dict_stats_empty_table(
|
||||
dict_stats_empty_index(index, empty_defrag_stats);
|
||||
}
|
||||
|
||||
table->stat_initialized = TRUE;
|
||||
table->stat = table->stat | dict_table_t::STATS_INITIALIZED;
|
||||
table->stats_mutex_unlock();
|
||||
}
|
||||
|
||||
@ -658,16 +658,10 @@ dict_stats_assert_initialized(
|
||||
/*==========================*/
|
||||
const dict_table_t* table) /*!< in: table */
|
||||
{
|
||||
ut_a(table->stat_initialized);
|
||||
|
||||
MEM_CHECK_DEFINED(&table->stats_last_recalc,
|
||||
sizeof table->stats_last_recalc);
|
||||
|
||||
MEM_CHECK_DEFINED(&table->stat_persistent,
|
||||
sizeof table->stat_persistent);
|
||||
|
||||
MEM_CHECK_DEFINED(&table->stats_auto_recalc,
|
||||
sizeof table->stats_auto_recalc);
|
||||
MEM_CHECK_DEFINED(&table->stat, sizeof table->stat);
|
||||
|
||||
MEM_CHECK_DEFINED(&table->stats_sample_pages,
|
||||
sizeof table->stats_sample_pages);
|
||||
@ -844,8 +838,8 @@ btr_estimate_number_of_different_key_vals(dict_index_t* index,
|
||||
ulint n_cols;
|
||||
ib_uint64_t* n_diff;
|
||||
ib_uint64_t* n_not_null;
|
||||
ibool stats_null_not_equal;
|
||||
uintmax_t n_sample_pages=1; /* number of pages to sample */
|
||||
bool stats_null_not_equal;
|
||||
uint32_t n_sample_pages=1; /* number of pages to sample */
|
||||
ulint not_empty_flag = 0;
|
||||
ulint total_external_size = 0;
|
||||
uintmax_t add_on;
|
||||
@ -883,11 +877,11 @@ btr_estimate_number_of_different_key_vals(dict_index_t* index,
|
||||
case SRV_STATS_NULLS_UNEQUAL:
|
||||
/* for both SRV_STATS_NULLS_IGNORED and SRV_STATS_NULLS_UNEQUAL
|
||||
case, we will treat NULLs as unequal value */
|
||||
stats_null_not_equal = TRUE;
|
||||
stats_null_not_equal = true;
|
||||
break;
|
||||
|
||||
case SRV_STATS_NULLS_EQUAL:
|
||||
stats_null_not_equal = FALSE;
|
||||
stats_null_not_equal = false;
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -938,19 +932,21 @@ btr_estimate_number_of_different_key_vals(dict_index_t* index,
|
||||
|
||||
so taking all case2 paths is I, our expression is:
|
||||
n_pages = S < I? min(I,L) : I
|
||||
*/
|
||||
if (index->stat_index_size > 1) {
|
||||
n_sample_pages = (srv_stats_transient_sample_pages < index->stat_index_size)
|
||||
? ut_min(index->stat_index_size,
|
||||
static_cast<ulint>(
|
||||
log2(double(index->stat_index_size))
|
||||
* double(srv_stats_transient_sample_pages)))
|
||||
: index->stat_index_size;
|
||||
*/
|
||||
if (uint32_t I = index->stat_index_size) {
|
||||
const uint32_t S{srv_stats_transient_sample_pages};
|
||||
n_sample_pages = S < I
|
||||
? std::min(I,
|
||||
uint32_t(log2(double(I))
|
||||
* double(S)))
|
||||
: I;
|
||||
}
|
||||
}
|
||||
|
||||
/* Sanity check */
|
||||
ut_ad(n_sample_pages > 0 && n_sample_pages <= (index->stat_index_size <= 1 ? 1 : index->stat_index_size));
|
||||
ut_ad(n_sample_pages);
|
||||
ut_ad(n_sample_pages <= (index->stat_index_size <= 1
|
||||
? 1 : index->stat_index_size));
|
||||
|
||||
/* We sample some pages in the index to get an estimate */
|
||||
btr_cur_t cursor;
|
||||
@ -1169,7 +1165,7 @@ invalid:
|
||||
|
||||
mtr.x_lock_space(index->table->space);
|
||||
|
||||
ulint dummy, size;
|
||||
uint32_t dummy, size;
|
||||
index->stat_index_size
|
||||
= fseg_n_reserved_pages(*root, PAGE_HEADER
|
||||
+ PAGE_BTR_SEG_LEAF
|
||||
@ -1226,7 +1222,7 @@ dict_stats_update_transient(
|
||||
ut_ad(!table->stats_mutex_is_owner());
|
||||
|
||||
dict_index_t* index;
|
||||
ulint sum_of_index_sizes = 0;
|
||||
uint32_t sum_of_index_sizes = 0;
|
||||
dberr_t err = DB_SUCCESS;
|
||||
|
||||
/* Find out the sizes of the indexes and how many different values
|
||||
@ -1285,7 +1281,7 @@ empty_table:
|
||||
|
||||
table->stat_modified_counter = 0;
|
||||
|
||||
table->stat_initialized = TRUE;
|
||||
table->stat = table->stat | dict_table_t::STATS_INITIALIZED;
|
||||
|
||||
table->stats_mutex_unlock();
|
||||
|
||||
@ -2225,8 +2221,8 @@ dict_stats_analyze_index_for_n_prefix(
|
||||
struct index_stats_t
|
||||
{
|
||||
std::vector<index_field_stats_t> stats;
|
||||
ulint index_size;
|
||||
ulint n_leaf_pages;
|
||||
uint32_t index_size;
|
||||
uint32_t n_leaf_pages;
|
||||
|
||||
index_stats_t(ulint n_uniq) : index_size(1), n_leaf_pages(1)
|
||||
{
|
||||
@ -2365,7 +2361,7 @@ empty_index:
|
||||
|
||||
uint16_t root_level = btr_page_get_level(root->page.frame);
|
||||
mtr.x_lock_space(index->table->space);
|
||||
ulint dummy, size;
|
||||
uint32_t dummy, size;
|
||||
result.index_size
|
||||
= fseg_n_reserved_pages(*root, PAGE_HEADER + PAGE_BTR_SEG_LEAF
|
||||
+ root->page.frame, &size, &mtr)
|
||||
@ -2742,7 +2738,7 @@ dict_stats_update_persistent(
|
||||
|
||||
table->stat_modified_counter = 0;
|
||||
|
||||
table->stat_initialized = TRUE;
|
||||
table->stat = table->stat | dict_table_t::STATS_INITIALIZED;
|
||||
|
||||
dict_stats_assert_initialized(table);
|
||||
|
||||
@ -3164,8 +3160,7 @@ dict_stats_fetch_table_stats_step(
|
||||
ut_a(len == 8);
|
||||
|
||||
table->stat_clustered_index_size
|
||||
= std::max<ulint>(
|
||||
(ulint) mach_read_from_8(data), 1);
|
||||
= std::max(mach_read_from_4(data + 4), 1U);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -3174,18 +3169,9 @@ dict_stats_fetch_table_stats_step(
|
||||
ut_a(dtype_get_mtype(type) == DATA_INT);
|
||||
ut_a(len == 8);
|
||||
|
||||
ulint stat_other_idx_size
|
||||
= (ulint) mach_read_from_8(data);
|
||||
if (!stat_other_idx_size
|
||||
&& UT_LIST_GET_LEN(table->indexes) > 1) {
|
||||
stat_other_idx_size
|
||||
= UT_LIST_GET_LEN(table->indexes) - 1;
|
||||
}
|
||||
table->stat_sum_of_other_index_sizes
|
||||
= std::max<ulint>(
|
||||
(ulint) mach_read_from_8(data),
|
||||
UT_LIST_GET_LEN(table->indexes) - 1);
|
||||
|
||||
table->stat_sum_of_other_index_sizes = std::max(
|
||||
mach_read_from_4(data + 4),
|
||||
uint32_t(UT_LIST_GET_LEN(table->indexes) - 1));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@ -3370,14 +3356,12 @@ dict_stats_fetch_index_stats_step(
|
||||
|
||||
if (stat_name_len == 4 /* strlen("size") */
|
||||
&& strncasecmp("size", stat_name, stat_name_len) == 0) {
|
||||
index->stat_index_size
|
||||
= std::max<ulint>((ulint) stat_value, 1);
|
||||
index->stat_index_size = std::max(uint32_t(stat_value), 1U);
|
||||
arg->stats_were_modified = true;
|
||||
} else if (stat_name_len == 12 /* strlen("n_leaf_pages") */
|
||||
&& strncasecmp("n_leaf_pages", stat_name, stat_name_len)
|
||||
== 0) {
|
||||
index->stat_n_leaf_pages
|
||||
= std::max<ulint>((ulint) stat_value, 1);
|
||||
index->stat_n_leaf_pages = std::max(uint32_t(stat_value), 1U);
|
||||
arg->stats_were_modified = true;
|
||||
} else if (stat_name_len == 12 /* strlen("n_page_split") */
|
||||
&& strncasecmp("n_page_split", stat_name, stat_name_len)
|
||||
@ -3648,7 +3632,9 @@ dict_stats_update_for_index(
|
||||
{
|
||||
DBUG_ENTER("dict_stats_update_for_index");
|
||||
|
||||
if (dict_stats_is_persistent_enabled(index->table)) {
|
||||
ut_ad(index->table->stat_initialized());
|
||||
|
||||
if (index->table->stats_is_persistent()) {
|
||||
|
||||
if (dict_stats_persistent_storage_check(false)) {
|
||||
index_stats_t stats = dict_stats_analyze_index(index);
|
||||
@ -3789,7 +3775,7 @@ dict_stats_update(
|
||||
/* If table is using persistent stats,
|
||||
then save the stats on disk */
|
||||
|
||||
if (dict_stats_is_persistent_enabled(table)) {
|
||||
if (table->stats_is_persistent()) {
|
||||
|
||||
if (dict_stats_persistent_storage_check(false)) {
|
||||
|
||||
@ -3806,7 +3792,7 @@ dict_stats_update(
|
||||
/* fetch requested, either fetch from persistent statistics
|
||||
storage or use the old method */
|
||||
|
||||
if (table->stat_initialized) {
|
||||
if (table->stat_initialized()) {
|
||||
return(DB_SUCCESS);
|
||||
}
|
||||
|
||||
@ -3850,7 +3836,7 @@ dict_stats_update(
|
||||
goto transient;
|
||||
}
|
||||
#endif
|
||||
if (dict_stats_auto_recalc_is_enabled(table)) {
|
||||
if (table->stats_is_auto_recalc()) {
|
||||
return(dict_stats_update(
|
||||
table,
|
||||
DICT_STATS_RECALC_PERSISTENT));
|
||||
|
@ -135,7 +135,9 @@ schedule new estimates for table and index statistics to be calculated.
|
||||
void dict_stats_update_if_needed_func(dict_table_t *table)
|
||||
#endif
|
||||
{
|
||||
if (UNIV_UNLIKELY(!table->stat_initialized)) {
|
||||
uint32_t stat{table->stat};
|
||||
|
||||
if (UNIV_UNLIKELY(!table->stat_initialized(stat))) {
|
||||
/* The table may have been evicted from dict_sys
|
||||
and reloaded internally by InnoDB for FOREIGN KEY
|
||||
processing, but not reloaded by the SQL layer.
|
||||
@ -154,13 +156,9 @@ void dict_stats_update_if_needed_func(dict_table_t *table)
|
||||
ulonglong counter = table->stat_modified_counter++;
|
||||
ulonglong n_rows = dict_table_get_n_rows(table);
|
||||
|
||||
if (dict_stats_is_persistent_enabled(table)) {
|
||||
if (table->name.is_temporary()) {
|
||||
return;
|
||||
}
|
||||
if (counter > n_rows / 10 /* 10% */
|
||||
&& dict_stats_auto_recalc_is_enabled(table)) {
|
||||
|
||||
if (table->stats_is_persistent(stat)) {
|
||||
if (table->stats_is_auto_recalc(stat)
|
||||
&& counter > n_rows / 10 && !table->name.is_temporary()) {
|
||||
#ifdef WITH_WSREP
|
||||
/* Do not add table to background
|
||||
statistic calculation if this thread is not a
|
||||
|
@ -1644,12 +1644,11 @@ fseg_find_last_used_frag_page_slot(
|
||||
/** Calculate reserved fragment page slots.
|
||||
@param inode file segment index
|
||||
@return number of fragment pages */
|
||||
static ulint fseg_get_n_frag_pages(const fseg_inode_t *inode)
|
||||
static uint32_t fseg_get_n_frag_pages(const fseg_inode_t *inode) noexcept
|
||||
{
|
||||
ulint i;
|
||||
ulint count = 0;
|
||||
uint32_t count = 0;
|
||||
|
||||
for (i = 0; i < FSEG_FRAG_ARR_N_SLOTS; i++) {
|
||||
for (ulint i = 0; i < FSEG_FRAG_ARR_N_SLOTS; i++) {
|
||||
if (FIL_NULL != fseg_get_nth_frag_page_no(inode, i)) {
|
||||
count++;
|
||||
}
|
||||
@ -1794,21 +1793,24 @@ Calculates the number of pages reserved by a segment, and how many pages are
|
||||
currently used.
|
||||
@return number of reserved pages */
|
||||
static
|
||||
ulint
|
||||
uint32_t
|
||||
fseg_n_reserved_pages_low(
|
||||
/*======================*/
|
||||
const fseg_inode_t* inode, /*!< in: segment inode */
|
||||
ulint* used) /*!< out: number of pages used (not
|
||||
uint32_t* used) /*!< out: number of pages used (not
|
||||
more than reserved) */
|
||||
noexcept
|
||||
{
|
||||
const uint32_t extent_size = FSP_EXTENT_SIZE;
|
||||
|
||||
*used = mach_read_from_4(inode + FSEG_NOT_FULL_N_USED)
|
||||
+ FSP_EXTENT_SIZE * flst_get_len(inode + FSEG_FULL)
|
||||
+ extent_size * flst_get_len(inode + FSEG_FULL)
|
||||
+ fseg_get_n_frag_pages(inode);
|
||||
|
||||
return fseg_get_n_frag_pages(inode)
|
||||
+ FSP_EXTENT_SIZE * flst_get_len(inode + FSEG_FREE)
|
||||
+ FSP_EXTENT_SIZE * flst_get_len(inode + FSEG_NOT_FULL)
|
||||
+ FSP_EXTENT_SIZE * flst_get_len(inode + FSEG_FULL);
|
||||
+ extent_size * flst_get_len(inode + FSEG_FREE)
|
||||
+ extent_size * flst_get_len(inode + FSEG_NOT_FULL)
|
||||
+ extent_size * flst_get_len(inode + FSEG_FULL);
|
||||
}
|
||||
|
||||
/** Calculate the number of pages reserved by a segment,
|
||||
@ -1818,9 +1820,9 @@ and how many pages are currently used.
|
||||
@param[out] used number of pages that are used (not more than reserved)
|
||||
@param[in,out] mtr mini-transaction
|
||||
@return number of reserved pages */
|
||||
ulint fseg_n_reserved_pages(const buf_block_t &block,
|
||||
const fseg_header_t *header, ulint *used,
|
||||
mtr_t *mtr)
|
||||
uint32_t fseg_n_reserved_pages(const buf_block_t &block,
|
||||
const fseg_header_t *header, uint32_t *used,
|
||||
mtr_t *mtr) noexcept
|
||||
{
|
||||
ut_ad(page_align(header) == block.page.frame);
|
||||
buf_block_t *iblock;
|
||||
@ -1845,7 +1847,7 @@ static dberr_t fseg_fill_free_list(const fseg_inode_t *inode,
|
||||
buf_block_t *iblock, fil_space_t *space,
|
||||
uint32_t hint, mtr_t *mtr)
|
||||
{
|
||||
ulint used;
|
||||
uint32_t used;
|
||||
|
||||
ut_ad(!((page_offset(inode) - FSEG_ARR_OFFSET) % FSEG_INODE_SIZE));
|
||||
ut_d(space->modify_check(*mtr));
|
||||
@ -1996,8 +1998,7 @@ fseg_alloc_free_page_low(
|
||||
dberr_t* err)
|
||||
{
|
||||
ib_id_t seg_id;
|
||||
ulint used;
|
||||
ulint reserved;
|
||||
uint32_t used, reserved;
|
||||
xdes_t* descr; /*!< extent of the hinted page */
|
||||
uint32_t ret_page; /*!< the allocated page offset, FIL_NULL
|
||||
if could not be allocated */
|
||||
|
@ -1622,7 +1622,7 @@ inline void ha_innobase::reload_statistics()
|
||||
if (table->is_readable())
|
||||
dict_stats_init(table);
|
||||
else
|
||||
table->stat_initialized= 1;
|
||||
table->stat.fetch_or(dict_table_t::STATS_INITIALIZED);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2978,6 +2978,44 @@ static int innobase_rollback_by_xid(handlerton*, XID *xid) noexcept
|
||||
return XAER_NOTA;
|
||||
}
|
||||
|
||||
/** Initialize the InnoDB persistent statistics attributes.
|
||||
@param table InnoDB table
|
||||
@param table_options MariaDB table options
|
||||
@param sar the value of STATS_AUTO_RECALC
|
||||
@param initialized whether the InnoDB statistics were already initialized
|
||||
@return whether table->stats_sample_pages needs to be initialized */
|
||||
static bool innodb_copy_stat_flags(dict_table_t *table,
|
||||
ulong table_options,
|
||||
enum_stats_auto_recalc sar,
|
||||
bool initialized) noexcept
|
||||
{
|
||||
if (table->is_temporary() || table->no_rollback())
|
||||
{
|
||||
table->stat= dict_table_t::STATS_INITIALIZED |
|
||||
dict_table_t::STATS_PERSISTENT_OFF | dict_table_t::STATS_AUTO_RECALC_OFF;
|
||||
table->stats_sample_pages= 1;
|
||||
return false;
|
||||
}
|
||||
|
||||
static_assert(HA_OPTION_STATS_PERSISTENT ==
|
||||
dict_table_t::STATS_PERSISTENT_ON << 11, "");
|
||||
static_assert(HA_OPTION_NO_STATS_PERSISTENT ==
|
||||
dict_table_t::STATS_PERSISTENT_OFF << 11, "");
|
||||
uint32_t stat=
|
||||
(table_options &
|
||||
(HA_OPTION_STATS_PERSISTENT | HA_OPTION_NO_STATS_PERSISTENT)) >> 11;
|
||||
static_assert(uint32_t{HA_STATS_AUTO_RECALC_ON} << 3 ==
|
||||
dict_table_t::STATS_AUTO_RECALC_ON, "");
|
||||
static_assert(uint32_t{HA_STATS_AUTO_RECALC_OFF} << 3 ==
|
||||
dict_table_t::STATS_AUTO_RECALC_OFF, "");
|
||||
static_assert(true == dict_table_t::STATS_INITIALIZED, "");
|
||||
stat|= (sar & (HA_STATS_AUTO_RECALC_ON | HA_STATS_AUTO_RECALC_OFF)) << 3 |
|
||||
initialized;
|
||||
|
||||
table->stat= stat;
|
||||
return true;
|
||||
}
|
||||
|
||||
/*********************************************************************//**
|
||||
Copy table flags from MySQL's HA_CREATE_INFO into an InnoDB table object.
|
||||
Those flags are stored in .frm file and end up in the MySQL table object,
|
||||
@ -2990,29 +3028,9 @@ innobase_copy_frm_flags_from_create_info(
|
||||
dict_table_t* innodb_table, /*!< in/out: InnoDB table */
|
||||
const HA_CREATE_INFO* create_info) /*!< in: create info */
|
||||
{
|
||||
ibool ps_on;
|
||||
ibool ps_off;
|
||||
|
||||
if (innodb_table->is_temporary()
|
||||
|| innodb_table->no_rollback()) {
|
||||
/* Temp tables do not use persistent stats. */
|
||||
ps_on = FALSE;
|
||||
ps_off = TRUE;
|
||||
} else {
|
||||
ps_on = create_info->table_options
|
||||
& HA_OPTION_STATS_PERSISTENT;
|
||||
ps_off = create_info->table_options
|
||||
& HA_OPTION_NO_STATS_PERSISTENT;
|
||||
}
|
||||
|
||||
dict_stats_set_persistent(innodb_table, ps_on, ps_off);
|
||||
|
||||
dict_stats_auto_recalc_set(
|
||||
innodb_table,
|
||||
create_info->stats_auto_recalc == HA_STATS_AUTO_RECALC_ON,
|
||||
create_info->stats_auto_recalc == HA_STATS_AUTO_RECALC_OFF);
|
||||
|
||||
innodb_table->stats_sample_pages = create_info->stats_sample_pages;
|
||||
if (innodb_copy_stat_flags(innodb_table, create_info->table_options,
|
||||
create_info->stats_auto_recalc, false))
|
||||
innodb_table->stats_sample_pages= create_info->stats_sample_pages;
|
||||
}
|
||||
|
||||
/*********************************************************************//**
|
||||
@ -3026,28 +3044,10 @@ innobase_copy_frm_flags_from_table_share(
|
||||
dict_table_t* innodb_table, /*!< in/out: InnoDB table */
|
||||
const TABLE_SHARE* table_share) /*!< in: table share */
|
||||
{
|
||||
ibool ps_on;
|
||||
ibool ps_off;
|
||||
|
||||
if (innodb_table->is_temporary()) {
|
||||
/* Temp tables do not use persistent stats */
|
||||
ps_on = FALSE;
|
||||
ps_off = TRUE;
|
||||
} else {
|
||||
ps_on = table_share->db_create_options
|
||||
& HA_OPTION_STATS_PERSISTENT;
|
||||
ps_off = table_share->db_create_options
|
||||
& HA_OPTION_NO_STATS_PERSISTENT;
|
||||
}
|
||||
|
||||
dict_stats_set_persistent(innodb_table, ps_on, ps_off);
|
||||
|
||||
dict_stats_auto_recalc_set(
|
||||
innodb_table,
|
||||
table_share->stats_auto_recalc == HA_STATS_AUTO_RECALC_ON,
|
||||
table_share->stats_auto_recalc == HA_STATS_AUTO_RECALC_OFF);
|
||||
|
||||
innodb_table->stats_sample_pages = table_share->stats_sample_pages;
|
||||
if (innodb_copy_stat_flags(innodb_table, table_share->db_create_options,
|
||||
table_share->stats_auto_recalc,
|
||||
innodb_table->stat_initialized()))
|
||||
innodb_table->stats_sample_pages= table_share->stats_sample_pages;
|
||||
}
|
||||
|
||||
/*********************************************************************//**
|
||||
@ -13387,6 +13387,8 @@ ha_innobase::discard_or_import_tablespace(
|
||||
DBUG_RETURN(HA_ERR_TABLE_NEEDS_UPGRADE);
|
||||
}
|
||||
|
||||
ut_ad(m_prebuilt->table->stat_initialized());
|
||||
|
||||
if (m_prebuilt->table->space == fil_system.sys_space) {
|
||||
ib_senderrf(
|
||||
m_prebuilt->trx->mysql_thd, IB_LOG_LEVEL_ERROR,
|
||||
@ -13460,7 +13462,7 @@ ha_innobase::discard_or_import_tablespace(
|
||||
err, m_prebuilt->table->flags, NULL));
|
||||
}
|
||||
|
||||
if (dict_stats_is_persistent_enabled(m_prebuilt->table)) {
|
||||
if (m_prebuilt->table->stats_is_persistent()) {
|
||||
dberr_t ret;
|
||||
|
||||
/* Adjust the persistent statistics. */
|
||||
@ -13645,7 +13647,7 @@ int ha_innobase::delete_table(const char *name)
|
||||
/* This looks like the rollback of ALTER TABLE...ADD PARTITION
|
||||
that was caused by MDL timeout. We could have written undo log
|
||||
for inserting the data into the new partitions. */
|
||||
if (table->stat_persistent != DICT_STATS_PERSISTENT_OFF)
|
||||
if (!(table->stat & dict_table_t::STATS_PERSISTENT_OFF))
|
||||
{
|
||||
/* We do not really know if we are holding MDL_EXCLUSIVE. Even
|
||||
though this code is handling the case that we are not holding
|
||||
@ -13660,7 +13662,7 @@ int ha_innobase::delete_table(const char *name)
|
||||
|
||||
DEBUG_SYNC(thd, "before_delete_table_stats");
|
||||
|
||||
if (err == DB_SUCCESS && dict_stats_is_persistent_enabled(table) &&
|
||||
if (err == DB_SUCCESS && table->stats_is_persistent() &&
|
||||
!table->is_stats_table())
|
||||
{
|
||||
table_stats= dict_table_open_on_name(TABLE_STATS_NAME, false,
|
||||
@ -14033,7 +14035,7 @@ int ha_innobase::truncate()
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(50));
|
||||
}
|
||||
|
||||
if (error == DB_SUCCESS && dict_stats_is_persistent_enabled(ib_table) &&
|
||||
if (error == DB_SUCCESS && ib_table->stats_is_persistent() &&
|
||||
!ib_table->is_stats_table())
|
||||
{
|
||||
table_stats= dict_table_open_on_name(TABLE_STATS_NAME, false,
|
||||
@ -14529,7 +14531,7 @@ ha_innobase::scan_time()
|
||||
|
||||
ulint stat_clustered_index_size;
|
||||
|
||||
ut_a(m_prebuilt->table->stat_initialized);
|
||||
ut_ad(m_prebuilt->table->stat_initialized());
|
||||
|
||||
stat_clustered_index_size =
|
||||
m_prebuilt->table->stat_clustered_index_size;
|
||||
@ -14656,7 +14658,7 @@ innodb_rec_per_key(
|
||||
rec_per_key_t rec_per_key;
|
||||
ib_uint64_t n_diff;
|
||||
|
||||
ut_a(index->table->stat_initialized);
|
||||
ut_ad(index->table->stat_initialized());
|
||||
|
||||
ut_ad(i < dict_index_get_n_unique(index));
|
||||
ut_ad(!dict_index_is_spatial(index));
|
||||
@ -14806,7 +14808,7 @@ ha_innobase::info_low(
|
||||
|
||||
m_prebuilt->trx->op_info = "updating table statistics";
|
||||
|
||||
if (dict_stats_is_persistent_enabled(ib_table)) {
|
||||
if (ib_table->stats_is_persistent()) {
|
||||
if (is_analyze) {
|
||||
if (!srv_read_only_mode) {
|
||||
dict_stats_recalc_pool_del(
|
||||
@ -14844,7 +14846,7 @@ ha_innobase::info_low(
|
||||
ulint stat_clustered_index_size;
|
||||
ulint stat_sum_of_other_index_sizes;
|
||||
|
||||
ut_a(ib_table->stat_initialized);
|
||||
ut_ad(ib_table->stat_initialized());
|
||||
|
||||
#if !defined NO_ELISION && !defined SUX_LOCK_GENERIC
|
||||
if (xbegin()) {
|
||||
@ -14998,7 +15000,7 @@ ha_innobase::info_low(
|
||||
auto _ = make_scope_exit([ib_table]() {
|
||||
ib_table->stats_shared_unlock(); });
|
||||
|
||||
ut_a(ib_table->stat_initialized);
|
||||
ut_ad(ib_table->stat_initialized());
|
||||
|
||||
for (uint i = 0; i < table->s->keys; i++) {
|
||||
ulong j;
|
||||
@ -15925,8 +15927,7 @@ ha_innobase::extra(
|
||||
/* During copy alter operation, InnoDB
|
||||
updates the stats only for non-persistent
|
||||
tables. */
|
||||
if (!dict_stats_is_persistent_enabled(
|
||||
m_prebuilt->table)) {
|
||||
if (!m_prebuilt->table->stats_is_persistent()) {
|
||||
dict_stats_update_if_needed(
|
||||
m_prebuilt->table, *trx);
|
||||
}
|
||||
@ -19156,12 +19157,12 @@ static MYSQL_SYSVAR_BOOL(stats_on_metadata, innobase_stats_on_metadata,
|
||||
" SHOW TABLE STATUS for tables that use transient statistics (off by default)",
|
||||
NULL, NULL, FALSE);
|
||||
|
||||
static MYSQL_SYSVAR_ULONGLONG(stats_transient_sample_pages,
|
||||
static MYSQL_SYSVAR_UINT(stats_transient_sample_pages,
|
||||
srv_stats_transient_sample_pages,
|
||||
PLUGIN_VAR_RQCMDARG,
|
||||
"The number of leaf index pages to sample when calculating transient"
|
||||
" statistics (if persistent statistics are not used, default 8)",
|
||||
NULL, NULL, 8, 1, ~0ULL, 0);
|
||||
NULL, NULL, 8, 1, ~0U, 0);
|
||||
|
||||
static MYSQL_SYSVAR_BOOL(stats_persistent, srv_stats_persistent,
|
||||
PLUGIN_VAR_OPCMDARG,
|
||||
@ -19177,12 +19178,12 @@ static MYSQL_SYSVAR_BOOL(stats_auto_recalc, srv_stats_auto_recalc,
|
||||
" new statistics)",
|
||||
NULL, NULL, TRUE);
|
||||
|
||||
static MYSQL_SYSVAR_ULONGLONG(stats_persistent_sample_pages,
|
||||
static MYSQL_SYSVAR_UINT(stats_persistent_sample_pages,
|
||||
srv_stats_persistent_sample_pages,
|
||||
PLUGIN_VAR_RQCMDARG,
|
||||
"The number of leaf index pages to sample when calculating persistent"
|
||||
" statistics (by ANALYZE, default 20)",
|
||||
NULL, NULL, 20, 1, ~0ULL, 0);
|
||||
NULL, NULL, 20, 1, ~0U, 0);
|
||||
|
||||
static MYSQL_SYSVAR_ULONGLONG(stats_modified_counter, srv_stats_modified_counter,
|
||||
PLUGIN_VAR_RQCMDARG,
|
||||
|
@ -11180,7 +11180,7 @@ alter_stats_norebuild(
|
||||
DBUG_ENTER("alter_stats_norebuild");
|
||||
DBUG_ASSERT(!ctx->need_rebuild());
|
||||
|
||||
if (!dict_stats_is_persistent_enabled(ctx->new_table)) {
|
||||
if (!ctx->new_table->stats_is_persistent()) {
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
@ -11214,8 +11214,7 @@ alter_stats_rebuild(
|
||||
{
|
||||
DBUG_ENTER("alter_stats_rebuild");
|
||||
|
||||
if (!table->space
|
||||
|| !dict_stats_is_persistent_enabled(table)) {
|
||||
if (!table->space || !table->stats_is_persistent()) {
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
|
@ -4777,9 +4777,9 @@ i_s_dict_fill_sys_tablestats(THD* thd, dict_table_t *table,
|
||||
|
||||
OK(field_store_string(fields[SYS_TABLESTATS_NAME],
|
||||
table->name.m_name));
|
||||
OK(fields[SYS_TABLESTATS_INIT]->store(table->stat_initialized, true));
|
||||
OK(fields[SYS_TABLESTATS_INIT]->store(table->stat_initialized(), true));
|
||||
|
||||
if (table->stat_initialized)
|
||||
if (table->stat_initialized())
|
||||
{
|
||||
OK(fields[SYS_TABLESTATS_NROW]->store(table->stat_n_rows, true));
|
||||
|
||||
|
@ -375,7 +375,7 @@ ibuf_size_update(
|
||||
ibuf.free_list_len = flst_get_len(root + PAGE_HEADER
|
||||
+ PAGE_BTR_IBUF_FREE_LIST);
|
||||
|
||||
ibuf.height = 1 + btr_page_get_level(root);
|
||||
ibuf.height = uint8_t(1 + btr_page_get_level(root));
|
||||
|
||||
/* the '1 +' is the ibuf header page */
|
||||
ibuf.size = ibuf.seg_size - (1 + ibuf.free_list_len);
|
||||
@ -443,18 +443,11 @@ err_exit:
|
||||
goto err_exit;
|
||||
}
|
||||
|
||||
/* At startup we intialize ibuf to have a maximum of
|
||||
CHANGE_BUFFER_DEFAULT_SIZE in terms of percentage of the
|
||||
buffer pool size. Once ibuf struct is initialized this
|
||||
value is updated with the user supplied size by calling
|
||||
ibuf_max_size_update(). */
|
||||
ibuf.max_size = ((buf_pool_get_curr_size() >> srv_page_size_shift)
|
||||
* CHANGE_BUFFER_DEFAULT_SIZE) / 100;
|
||||
|
||||
mysql_mutex_init(ibuf_mutex_key, &ibuf_mutex, nullptr);
|
||||
mysql_mutex_init(ibuf_pessimistic_insert_mutex_key,
|
||||
&ibuf_pessimistic_insert_mutex, nullptr);
|
||||
|
||||
ibuf_max_size_update(CHANGE_BUFFER_DEFAULT_SIZE);
|
||||
mysql_mutex_lock(&ibuf_mutex);
|
||||
ibuf_size_update(root);
|
||||
mysql_mutex_unlock(&ibuf_mutex);
|
||||
@ -506,10 +499,12 @@ ibuf_max_size_update(
|
||||
percentage of the buffer pool size */
|
||||
{
|
||||
if (UNIV_UNLIKELY(!ibuf.index)) return;
|
||||
ulint new_size = ((buf_pool_get_curr_size() >> srv_page_size_shift)
|
||||
* new_val) / 100;
|
||||
ulint new_size = std::min<ulint>(
|
||||
(buf_pool_get_curr_size() >> srv_page_size_shift) * new_val
|
||||
/ 100, uint32_t(~0U));
|
||||
|
||||
mysql_mutex_lock(&ibuf_mutex);
|
||||
ibuf.max_size = new_size;
|
||||
ibuf.max_size = uint32_t(new_size);
|
||||
mysql_mutex_unlock(&ibuf_mutex);
|
||||
}
|
||||
|
||||
@ -4483,17 +4478,17 @@ ibuf_print(
|
||||
return;
|
||||
}
|
||||
|
||||
const ulint size= ibuf.size;
|
||||
const ulint free_list_len= ibuf.free_list_len;
|
||||
const ulint seg_size= ibuf.seg_size;
|
||||
const uint32_t size= ibuf.size;
|
||||
const uint32_t free_list_len= ibuf.free_list_len;
|
||||
const uint32_t seg_size= ibuf.seg_size;
|
||||
mysql_mutex_unlock(&ibuf_mutex);
|
||||
|
||||
fprintf(file,
|
||||
"-------------\n"
|
||||
"INSERT BUFFER\n"
|
||||
"-------------\n"
|
||||
"size " ULINTPF ", free list len " ULINTPF ","
|
||||
" seg size " ULINTPF ", " ULINTPF " merges\n",
|
||||
"size %" PRIu32 ", free list len %" PRIu32 ","
|
||||
" seg size %" PRIu32 ", " ULINTPF " merges\n",
|
||||
size, free_list_len, seg_size, ulint{ibuf.n_merges});
|
||||
ibuf_print_ops("merged operations:\n", ibuf.n_merged_ops, file);
|
||||
ibuf_print_ops("discarded operations:\n", ibuf.n_discarded_ops, file);
|
||||
|
@ -674,7 +674,7 @@ TPOOL_SUPPRESS_TSAN
|
||||
@return estimated number of rows */
|
||||
inline uint64_t dict_table_get_n_rows(const dict_table_t *table)
|
||||
{
|
||||
ut_ad(table->stat_initialized);
|
||||
ut_ad(table->stat_initialized());
|
||||
return table->stat_n_rows;
|
||||
}
|
||||
|
||||
|
@ -1106,10 +1106,10 @@ struct dict_index_t {
|
||||
is indexed from 0 to n_uniq-1); This
|
||||
is used when innodb_stats_method is
|
||||
"nulls_ignored". */
|
||||
ulint stat_index_size;
|
||||
uint32_t stat_index_size;
|
||||
/*!< approximate index size in
|
||||
database pages */
|
||||
ulint stat_n_leaf_pages;
|
||||
uint32_t stat_n_leaf_pages;
|
||||
/*!< approximate number of leaf pages in the
|
||||
index tree */
|
||||
bool stats_error_printed;
|
||||
@ -2358,63 +2358,32 @@ public:
|
||||
/** Statistics for query optimization. Mostly protected by
|
||||
dict_sys.latch and stats_mutex_lock(). @{ */
|
||||
|
||||
/** TRUE if statistics have been calculated the first time after
|
||||
database startup or table creation. */
|
||||
unsigned stat_initialized:1;
|
||||
|
||||
/** Timestamp of last recalc of the stats. */
|
||||
time_t stats_last_recalc;
|
||||
|
||||
/** The two bits below are set in the 'stat_persistent' member. They
|
||||
have the following meaning:
|
||||
1. _ON=0, _OFF=0, no explicit persistent stats setting for this table,
|
||||
the value of the global srv_stats_persistent is used to determine
|
||||
whether the table has persistent stats enabled or not
|
||||
2. _ON=0, _OFF=1, persistent stats are explicitly disabled for this
|
||||
table, regardless of the value of the global srv_stats_persistent
|
||||
3. _ON=1, _OFF=0, persistent stats are explicitly enabled for this
|
||||
table, regardless of the value of the global srv_stats_persistent
|
||||
4. _ON=1, _OFF=1, not allowed, we assert if this ever happens. */
|
||||
#define DICT_STATS_PERSISTENT_ON (1 << 1)
|
||||
#define DICT_STATS_PERSISTENT_OFF (1 << 2)
|
||||
static constexpr uint32_t STATS_INITIALIZED= 1U;
|
||||
static constexpr uint32_t STATS_PERSISTENT_ON= 1U << 1;
|
||||
static constexpr uint32_t STATS_PERSISTENT_OFF= 1U << 2;
|
||||
static constexpr uint32_t STATS_AUTO_RECALC_ON= 1U << 3;
|
||||
static constexpr uint32_t STATS_AUTO_RECALC_OFF= 1U << 4;
|
||||
|
||||
/** Indicates whether the table uses persistent stats or not. See
|
||||
DICT_STATS_PERSISTENT_ON and DICT_STATS_PERSISTENT_OFF. */
|
||||
ib_uint32_t stat_persistent;
|
||||
/** flags for index cardinality statistics */
|
||||
Atomic_relaxed<uint32_t> stat;
|
||||
/** Approximate clustered index size in database pages. */
|
||||
uint32_t stat_clustered_index_size;
|
||||
/** Approximate size of other indexes in database pages. */
|
||||
uint32_t stat_sum_of_other_index_sizes;
|
||||
|
||||
/** The two bits below are set in the 'stats_auto_recalc' member. They
|
||||
have the following meaning:
|
||||
1. _ON=0, _OFF=0, no explicit auto recalc setting for this table, the
|
||||
value of the global srv_stats_persistent_auto_recalc is used to
|
||||
determine whether the table has auto recalc enabled or not
|
||||
2. _ON=0, _OFF=1, auto recalc is explicitly disabled for this table,
|
||||
regardless of the value of the global srv_stats_persistent_auto_recalc
|
||||
3. _ON=1, _OFF=0, auto recalc is explicitly enabled for this table,
|
||||
regardless of the value of the global srv_stats_persistent_auto_recalc
|
||||
4. _ON=1, _OFF=1, not allowed, we assert if this ever happens. */
|
||||
#define DICT_STATS_AUTO_RECALC_ON (1 << 1)
|
||||
#define DICT_STATS_AUTO_RECALC_OFF (1 << 2)
|
||||
|
||||
/** Indicates whether the table uses automatic recalc for persistent
|
||||
stats or not. See DICT_STATS_AUTO_RECALC_ON and
|
||||
DICT_STATS_AUTO_RECALC_OFF. */
|
||||
ib_uint32_t stats_auto_recalc;
|
||||
|
||||
/** The number of pages to sample for this table during persistent
|
||||
stats estimation. If this is 0, then the value of the global
|
||||
srv_stats_persistent_sample_pages will be used instead. */
|
||||
ulint stats_sample_pages;
|
||||
/** The number of pages to sample for this table during persistent
|
||||
stats estimation. If this is 0, then the value of the global
|
||||
srv_stats_persistent_sample_pages will be used instead. */
|
||||
uint32_t stats_sample_pages;
|
||||
|
||||
/** Approximate number of rows in the table. We periodically calculate
|
||||
new estimates. */
|
||||
ib_uint64_t stat_n_rows;
|
||||
|
||||
/** Approximate clustered index size in database pages. */
|
||||
ulint stat_clustered_index_size;
|
||||
|
||||
/** Approximate size of other indexes in database pages. */
|
||||
ulint stat_sum_of_other_index_sizes;
|
||||
|
||||
/** How many rows are modified since last stats recalc. When a row is
|
||||
inserted, updated, or deleted, we add 1 to this number; we calculate
|
||||
new estimates for the table and the indexes if the table has changed
|
||||
@ -2551,6 +2520,35 @@ public:
|
||||
/** @return the index for that starts with a specific column */
|
||||
dict_index_t *get_index(const dict_col_t &col) const;
|
||||
|
||||
/** @return whether the statistics are initialized */
|
||||
static bool stat_initialized(uint32_t stat) noexcept
|
||||
{ return stat & STATS_INITIALIZED; }
|
||||
|
||||
/** @return whether STATS_PERSISTENT is enabled */
|
||||
static bool stats_is_persistent(uint32_t stat) noexcept
|
||||
{
|
||||
ut_ad(~(stat & (STATS_PERSISTENT_ON | STATS_PERSISTENT_OFF)));
|
||||
if (stat & STATS_PERSISTENT_ON) return true;
|
||||
return !(stat & STATS_PERSISTENT_OFF) && srv_stats_persistent;
|
||||
}
|
||||
/** @return whether STATS_AUTO_RECALC is enabled */
|
||||
static bool stats_is_auto_recalc(uint32_t stat) noexcept
|
||||
{
|
||||
ut_ad(stat_initialized(stat));
|
||||
ut_ad(~(stat & (STATS_AUTO_RECALC_ON | STATS_AUTO_RECALC_OFF)));
|
||||
if (stat & STATS_AUTO_RECALC_ON) return true;
|
||||
return !(stat & STATS_AUTO_RECALC_OFF) && srv_stats_auto_recalc;
|
||||
}
|
||||
|
||||
/** @return whether the statistics are initialized */
|
||||
bool stat_initialized() const noexcept { return stat_initialized(stat); }
|
||||
/** @return whether STATS_PERSISTENT is enabled */
|
||||
bool stats_is_persistent() const noexcept
|
||||
{ return stats_is_persistent(stat); }
|
||||
/** @return whether STATS_AUTO_RECALC is enabled */
|
||||
bool stats_is_auto_recalc() const noexcept
|
||||
{ return stats_is_auto_recalc(stat); }
|
||||
|
||||
/** Create metadata.
|
||||
@param name table name
|
||||
@param space tablespace
|
||||
|
@ -52,44 +52,6 @@ enum dict_stats_upd_option_t {
|
||||
otherwise do nothing */
|
||||
};
|
||||
|
||||
/*********************************************************************//**
|
||||
Set the persistent statistics flag for a given table. This is set only
|
||||
in the in-memory table object and is not saved on disk. It will be read
|
||||
from the .frm file upon first open from MySQL after a server restart. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
dict_stats_set_persistent(
|
||||
/*======================*/
|
||||
dict_table_t* table, /*!< in/out: table */
|
||||
ibool ps_on, /*!< in: persistent stats explicitly enabled */
|
||||
ibool ps_off) /*!< in: persistent stats explicitly disabled */
|
||||
MY_ATTRIBUTE((nonnull));
|
||||
|
||||
/** @return whether persistent statistics is enabled for a given table */
|
||||
UNIV_INLINE
|
||||
bool
|
||||
dict_stats_is_persistent_enabled(const dict_table_t* table)
|
||||
MY_ATTRIBUTE((nonnull, warn_unused_result));
|
||||
|
||||
/*********************************************************************//**
|
||||
Set the auto recalc flag for a given table (only honored for a persistent
|
||||
stats enabled table). The flag is set only in the in-memory table object
|
||||
and is not saved in InnoDB files. It will be read from the .frm file upon
|
||||
first open from MySQL after a server restart. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
dict_stats_auto_recalc_set(
|
||||
/*=======================*/
|
||||
dict_table_t* table, /*!< in/out: table */
|
||||
ibool auto_recalc_on, /*!< in: explicitly enabled */
|
||||
ibool auto_recalc_off); /*!< in: explicitly disabled */
|
||||
|
||||
/** @return whether auto recalc is enabled for a given table*/
|
||||
UNIV_INLINE
|
||||
bool
|
||||
dict_stats_auto_recalc_is_enabled(const dict_table_t* table)
|
||||
MY_ATTRIBUTE((nonnull, warn_unused_result));
|
||||
|
||||
/*********************************************************************//**
|
||||
Initialize table's stats for the first time when opening a table. */
|
||||
UNIV_INLINE
|
||||
|
@ -25,120 +25,6 @@ Created Jan 23, 2012 Vasil Dimov
|
||||
*******************************************************/
|
||||
|
||||
#include "dict0dict.h"
|
||||
#include "srv0srv.h"
|
||||
|
||||
/*********************************************************************//**
|
||||
Set the persistent statistics flag for a given table. This is set only
|
||||
in the in-memory table object and is not saved on disk. It will be read
|
||||
from the .frm file upon first open from MySQL after a server restart. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
dict_stats_set_persistent(
|
||||
/*======================*/
|
||||
dict_table_t* table, /*!< in/out: table */
|
||||
ibool ps_on, /*!< in: persistent stats explicitly enabled */
|
||||
ibool ps_off) /*!< in: persistent stats explicitly disabled */
|
||||
{
|
||||
/* Not allowed to have both flags set, but a CREATE or ALTER
|
||||
statement that contains "STATS_PERSISTENT=0 STATS_PERSISTENT=1" would
|
||||
end up having both set. In this case we clear the OFF flag. */
|
||||
if (ps_on && ps_off) {
|
||||
ps_off = FALSE;
|
||||
}
|
||||
|
||||
ib_uint32_t stat_persistent = 0;
|
||||
|
||||
if (ps_on) {
|
||||
stat_persistent |= DICT_STATS_PERSISTENT_ON;
|
||||
}
|
||||
|
||||
if (ps_off) {
|
||||
stat_persistent |= DICT_STATS_PERSISTENT_OFF;
|
||||
}
|
||||
|
||||
/* we rely on this assignment to be atomic */
|
||||
table->stat_persistent = stat_persistent;
|
||||
}
|
||||
|
||||
/** @return whether persistent statistics is enabled for a given table */
|
||||
UNIV_INLINE
|
||||
bool
|
||||
dict_stats_is_persistent_enabled(const dict_table_t* table)
|
||||
{
|
||||
/* Because of the nature of this check (non-locking) it is possible
|
||||
that a table becomes:
|
||||
* PS-disabled immediately after this function has returned TRUE or
|
||||
* PS-enabled immediately after this function has returned FALSE.
|
||||
This means that it is possible that we do:
|
||||
+ dict_stats_update(DICT_STATS_RECALC_PERSISTENT) on a table that has
|
||||
just been PS-disabled or
|
||||
+ dict_stats_update(DICT_STATS_RECALC_TRANSIENT) on a table that has
|
||||
just been PS-enabled.
|
||||
This is acceptable. Avoiding this would mean that we would have to
|
||||
hold dict_sys.latch or stats_mutex_lock() like for accessing the
|
||||
other ::stat_ members which would be too big performance penalty,
|
||||
especially when this function is called from
|
||||
dict_stats_update_if_needed(). */
|
||||
|
||||
/* we rely on this read to be atomic */
|
||||
ib_uint32_t stat_persistent = table->stat_persistent;
|
||||
|
||||
if (stat_persistent & DICT_STATS_PERSISTENT_ON) {
|
||||
ut_ad(!(stat_persistent & DICT_STATS_PERSISTENT_OFF));
|
||||
return(true);
|
||||
} else if (stat_persistent & DICT_STATS_PERSISTENT_OFF) {
|
||||
return(false);
|
||||
} else {
|
||||
return(srv_stats_persistent);
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************//**
|
||||
Set the auto recalc flag for a given table (only honored for a persistent
|
||||
stats enabled table). The flag is set only in the in-memory table object
|
||||
and is not saved in InnoDB files. It will be read from the .frm file upon
|
||||
first open from MySQL after a server restart. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
dict_stats_auto_recalc_set(
|
||||
/*=======================*/
|
||||
dict_table_t* table, /*!< in/out: table */
|
||||
ibool auto_recalc_on, /*!< in: explicitly enabled */
|
||||
ibool auto_recalc_off) /*!< in: explicitly disabled */
|
||||
{
|
||||
ut_ad(!auto_recalc_on || !auto_recalc_off);
|
||||
|
||||
ib_uint32_t stats_auto_recalc = 0;
|
||||
|
||||
if (auto_recalc_on) {
|
||||
stats_auto_recalc |= DICT_STATS_AUTO_RECALC_ON;
|
||||
}
|
||||
|
||||
if (auto_recalc_off) {
|
||||
stats_auto_recalc |= DICT_STATS_AUTO_RECALC_OFF;
|
||||
}
|
||||
|
||||
/* we rely on this assignment to be atomic */
|
||||
table->stats_auto_recalc = stats_auto_recalc;
|
||||
}
|
||||
|
||||
/** @return whether auto recalc is enabled for a given table*/
|
||||
UNIV_INLINE
|
||||
bool
|
||||
dict_stats_auto_recalc_is_enabled(const dict_table_t* table)
|
||||
{
|
||||
/* we rely on this read to be atomic */
|
||||
ib_uint32_t stats_auto_recalc = table->stats_auto_recalc;
|
||||
|
||||
if (stats_auto_recalc & DICT_STATS_AUTO_RECALC_ON) {
|
||||
ut_ad(!(stats_auto_recalc & DICT_STATS_AUTO_RECALC_OFF));
|
||||
return(true);
|
||||
} else if (stats_auto_recalc & DICT_STATS_AUTO_RECALC_OFF) {
|
||||
return(false);
|
||||
} else {
|
||||
return(srv_stats_auto_recalc);
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************//**
|
||||
Initialize table's stats for the first time when opening a table. */
|
||||
@ -150,13 +36,15 @@ dict_stats_init(
|
||||
{
|
||||
ut_ad(!table->stats_mutex_is_owner());
|
||||
|
||||
if (table->stat_initialized) {
|
||||
uint32_t stat = table->stat;
|
||||
|
||||
if (stat & dict_table_t::STATS_INITIALIZED) {
|
||||
return;
|
||||
}
|
||||
|
||||
dict_stats_upd_option_t opt;
|
||||
|
||||
if (dict_stats_is_persistent_enabled(table)) {
|
||||
if (table->stats_is_persistent(stat)) {
|
||||
opt = DICT_STATS_FETCH_ONLY_IF_NOT_IN_MEMORY;
|
||||
} else {
|
||||
opt = DICT_STATS_RECALC_TRANSIENT;
|
||||
@ -178,7 +66,7 @@ dict_stats_deinit(
|
||||
ut_ad(table->get_ref_count() == 0);
|
||||
|
||||
#ifdef HAVE_valgrind
|
||||
if (!table->stat_initialized) {
|
||||
if (!table->stat_initialized()) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -215,5 +103,6 @@ dict_stats_deinit(
|
||||
sizeof(index->stat_n_leaf_pages));
|
||||
}
|
||||
#endif /* HAVE_valgrind */
|
||||
table->stat_initialized = FALSE;
|
||||
|
||||
table->stat = table->stat & ~dict_table_t::STATS_INITIALIZED;
|
||||
}
|
||||
|
@ -355,9 +355,9 @@ and how many pages are currently used.
|
||||
@param[out] used number of pages that are used (not more than reserved)
|
||||
@param[in,out] mtr mini-transaction
|
||||
@return number of reserved pages */
|
||||
ulint fseg_n_reserved_pages(const buf_block_t &block,
|
||||
const fseg_header_t *header, ulint *used,
|
||||
mtr_t *mtr)
|
||||
uint32_t fseg_n_reserved_pages(const buf_block_t &block,
|
||||
const fseg_header_t *header, uint32_t *used,
|
||||
mtr_t *mtr) noexcept
|
||||
MY_ATTRIBUTE((nonnull));
|
||||
/**********************************************************************//**
|
||||
Allocates a single free page from a segment. This function implements
|
||||
|
@ -62,11 +62,11 @@ extern ulong innodb_change_buffering;
|
||||
|
||||
/** Insert buffer struct */
|
||||
struct ibuf_t{
|
||||
Atomic_relaxed<ulint> size; /*!< current size of the ibuf index
|
||||
Atomic_relaxed<uint32_t> size; /*!< current size of the ibuf index
|
||||
tree, in pages */
|
||||
Atomic_relaxed<ulint> max_size; /*!< recommended maximum size of the
|
||||
Atomic_relaxed<uint32_t> max_size;/*!< recommended maximum size of the
|
||||
ibuf index tree, in pages */
|
||||
ulint seg_size; /*!< allocated pages of the file
|
||||
uint32_t seg_size; /*!< allocated pages of the file
|
||||
segment containing ibuf header and
|
||||
tree */
|
||||
bool empty; /*!< Protected by the page
|
||||
@ -75,8 +75,8 @@ struct ibuf_t{
|
||||
(FSP_IBUF_TREE_ROOT_PAGE_NO). true
|
||||
if and only if the insert
|
||||
buffer tree is empty. */
|
||||
ulint free_list_len; /*!< length of the free list */
|
||||
ulint height; /*!< tree height */
|
||||
uint8_t height; /*!< tree height */
|
||||
uint32_t free_list_len; /*!< length of the free list */
|
||||
dict_index_t* index; /*!< insert buffer index */
|
||||
|
||||
/** number of pages merged */
|
||||
|
@ -294,9 +294,9 @@ extern uint srv_fast_shutdown;
|
||||
|
||||
extern ibool srv_innodb_status;
|
||||
|
||||
extern unsigned long long srv_stats_transient_sample_pages;
|
||||
extern uint32_t srv_stats_transient_sample_pages;
|
||||
extern my_bool srv_stats_persistent;
|
||||
extern unsigned long long srv_stats_persistent_sample_pages;
|
||||
extern uint32_t srv_stats_persistent_sample_pages;
|
||||
extern my_bool srv_stats_auto_recalc;
|
||||
extern my_bool srv_stats_include_delete_marked;
|
||||
extern unsigned long long srv_stats_modified_counter;
|
||||
|
@ -1599,7 +1599,7 @@ row_update_for_mysql(row_prebuilt_t* prebuilt)
|
||||
ut_a(prebuilt->magic_n == ROW_PREBUILT_ALLOCATED);
|
||||
ut_a(prebuilt->magic_n2 == ROW_PREBUILT_ALLOCATED);
|
||||
ut_a(prebuilt->template_type == ROW_MYSQL_WHOLE_ROW);
|
||||
ut_ad(table->stat_initialized);
|
||||
ut_ad(table->stat_initialized());
|
||||
|
||||
if (!table->is_readable()) {
|
||||
return row_mysql_get_table_error(trx, table);
|
||||
|
@ -1564,7 +1564,7 @@ row_purge_record_func(
|
||||
case TRX_UNDO_DEL_MARK_REC:
|
||||
purged = row_purge_del_mark(node);
|
||||
if (purged) {
|
||||
if (node->table->stat_initialized
|
||||
if (node->table->stat_initialized()
|
||||
&& srv_stats_include_delete_marked) {
|
||||
dict_stats_update_if_needed(
|
||||
node->table, *thr->graph->trx);
|
||||
|
@ -614,7 +614,7 @@ row_undo_ins(
|
||||
err = row_undo_ins_remove_clust_rec(node);
|
||||
}
|
||||
|
||||
if (err == DB_SUCCESS && node->table->stat_initialized) {
|
||||
if (err == DB_SUCCESS && node->table->stat_initialized()) {
|
||||
/* Not protected by dict_sys.latch
|
||||
or table->stats_mutex_lock() for
|
||||
performance reasons, we would rather get garbage
|
||||
|
@ -1388,7 +1388,7 @@ rollback_clust:
|
||||
bool update_statistics
|
||||
= !(node->cmpl_info & UPD_NODE_NO_ORD_CHANGE);
|
||||
|
||||
if (err == DB_SUCCESS && node->table->stat_initialized) {
|
||||
if (err == DB_SUCCESS && node->table->stat_initialized()) {
|
||||
switch (node->rec_type) {
|
||||
case TRX_UNDO_UPD_EXIST_REC:
|
||||
break;
|
||||
|
@ -291,13 +291,13 @@ this many index pages, there are 2 ways to calculate statistics:
|
||||
in the innodb database.
|
||||
* quick transient stats, that are used if persistent stats for the given
|
||||
table/index are not found in the innodb database */
|
||||
unsigned long long srv_stats_transient_sample_pages;
|
||||
uint32_t srv_stats_transient_sample_pages;
|
||||
/** innodb_stats_persistent */
|
||||
my_bool srv_stats_persistent;
|
||||
/** innodb_stats_include_delete_marked */
|
||||
my_bool srv_stats_include_delete_marked;
|
||||
/** innodb_stats_persistent_sample_pages */
|
||||
unsigned long long srv_stats_persistent_sample_pages;
|
||||
uint32_t srv_stats_persistent_sample_pages;
|
||||
/** innodb_stats_auto_recalc */
|
||||
my_bool srv_stats_auto_recalc;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user