Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions mysql-test/main/opt_context_replay_basic.result
Original file line number Diff line number Diff line change
Expand Up @@ -315,4 +315,26 @@ id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 system NULL NULL NULL NULL 1
set optimizer_replay_context='';
drop table t1;
#
# MDEV-39440: Failed to match the stats from replay context with the optimizer stats
#
create table t1 (btn char(10) not null, key using HASH (btn)) engine=heap;
insert into t1 values ("a"),("b"),("c"),("d");
alter table t1 add column new_col char(1) not null, add key using HASH (btn,new_col), drop key btn;
update t1 set new_col=left(btn,1);
set optimizer_record_context=1;
explain select * from t1 where btn="a";
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL btn NULL NULL NULL 4 Using where
select context into dumpfile "../../tmp/dump1.sql"
from information_schema.optimizer_context;
set optimizer_record_context=0;
drop table t1;
set optimizer_replay_context='opt_context';
# Same query as above, must have same explain:
explain select * from t1 where btn="a";
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL btn NULL NULL NULL 4 Using where
set optimizer_replay_context='';
drop table t1;
drop database db1;
27 changes: 27 additions & 0 deletions mysql-test/main/opt_context_replay_basic.test
Original file line number Diff line number Diff line change
Expand Up @@ -173,4 +173,31 @@ set optimizer_replay_context='';
--remove_file "$MYSQLTEST_VARDIR/tmp/dump1.sql"
drop table t1;

--echo #
--echo # MDEV-39440: Failed to match the stats from replay context with the optimizer stats
--echo #
create table t1 (btn char(10) not null, key using HASH (btn)) engine=heap;
insert into t1 values ("a"),("b"),("c"),("d");
alter table t1 add column new_col char(1) not null, add key using HASH (btn,new_col), drop key btn;
update t1 set new_col=left(btn,1);

set optimizer_record_context=1;
explain select * from t1 where btn="a";
select context into dumpfile "../../tmp/dump1.sql"
from information_schema.optimizer_context;
set optimizer_record_context=0;
drop table t1;
--disable_query_log
--disable_result_log
--source "$MYSQLTEST_VARDIR/tmp/dump1.sql"
--enable_query_log
--enable_result_log
set optimizer_replay_context='opt_context';
--echo # Same query as above, must have same explain:
explain select * from t1 where btn="a";

set optimizer_replay_context='';
--remove_file "$MYSQLTEST_VARDIR/tmp/dump1.sql"
drop table t1;

drop database db1;
23 changes: 14 additions & 9 deletions sql/opt_context_store_replay.cc
Original file line number Diff line number Diff line change
Expand Up @@ -775,13 +775,9 @@ Optimizer_context_recorder::search(uchar *tbl_name, size_t tbl_name_len)
}

void Optimizer_context_recorder::record_multi_range_read_info_const(
const TABLE_LIST *tbl,
uint keynr,
Range_print_enumerator *ranges,
ha_rows rows,
const Cost_estimate *cost,
ha_rows max_index_blocks,
ha_rows max_row_blocks)
const TABLE_LIST *tbl, uint keynr, Range_print_enumerator *ranges,
ha_rows rows, const Cost_estimate *cost, const ha_rows *max_index_blocks,
const ha_rows *max_row_blocks)
{
/*
Do not record calls that are made at execution phase by "Range checked
Expand All @@ -801,8 +797,17 @@ void Optimizer_context_recorder::record_multi_range_read_info_const(

range_ctx->rows= rows;
range_ctx->cost= *cost;
range_ctx->max_index_blocks= max_index_blocks;
range_ctx->max_row_blocks= max_row_blocks;
if (rows != HA_POS_ERROR)
{
range_ctx->max_index_blocks= *max_index_blocks;
range_ctx->max_row_blocks= *max_row_blocks;
}
else
{
// Not provided. Write 0.
range_ctx->max_index_blocks= 0;
range_ctx->max_row_blocks= 0;
}

while (!ranges->next())
{
Expand Down
7 changes: 3 additions & 4 deletions sql/opt_context_store_replay.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,13 +47,12 @@ class Optimizer_context_recorder

~Optimizer_context_recorder();

void record_multi_range_read_info_const(const TABLE_LIST *tbl,
uint keynr,
void record_multi_range_read_info_const(const TABLE_LIST *tbl, uint keynr,
Range_print_enumerator *ranges,
ha_rows rows,
const Cost_estimate *cost,
ha_rows max_index_blocks,
ha_rows max_row_blocks);
const ha_rows *max_index_blocks,
const ha_rows *max_row_blocks);

void record_cost_index_read(const TABLE_LIST *tbl,
uint key, ha_rows records, bool eq_ref,
Expand Down
24 changes: 14 additions & 10 deletions sql/opt_range.cc
Original file line number Diff line number Diff line change
Expand Up @@ -12471,6 +12471,7 @@ ha_rows check_quick_select(PARAM *param, uint idx, ha_rows limit,
ha_rows replay_ctx_max_index_blocks;
ha_rows replay_ctx_max_row_blocks;
bool replay_ctx_rc;
TABLE::OPT_RANGE *range= param->table->opt_range + keynr;
DBUG_ENTER("check_quick_select");

/* Range not calculated yet */
Expand Down Expand Up @@ -12534,7 +12535,6 @@ ha_rows check_quick_select(PARAM *param, uint idx, ha_rows limit,
param->quick_rows[keynr]= rows;
if (rows != HA_POS_ERROR)
{
TABLE::OPT_RANGE *range= param->table->opt_range + keynr;
ha_rows table_records= param->table->stat_records();
if (rows > table_records)
{
Expand All @@ -12560,15 +12560,6 @@ ha_rows check_quick_select(PARAM *param, uint idx, ha_rows limit,
range->max_row_blocks=
MY_MIN(file->row_blocks(), rows * file->stats.block_size / IO_SIZE);

if (Optimizer_context_recorder *rec= param->thd->opt_ctx_recorder)
{
Range_print_enumerator_impl range_iter(param, idx, tree);
rec->record_multi_range_read_info_const(param->table->pos_in_table_list,
keynr, &range_iter, rows, cost,
range->max_index_blocks,
range->max_row_blocks);
}

if (update_tbl_stats)
{
param->table->opt_range_keys.set_bit(keynr);
Expand Down Expand Up @@ -12597,6 +12588,19 @@ ha_rows check_quick_select(PARAM *param, uint idx, ha_rows limit,
}
}

if (Optimizer_context_recorder *rec= param->thd->opt_ctx_recorder)
{
Range_print_enumerator_impl range_iter(param, idx, tree);
/*
We pass range->max_index_blocks, and range->max_row_blocks by address,
as they might not have been initialized except when rows != HA_POS_ERROR.
This way, ASAN and valgrind also wouldn't complain.
*/
rec->record_multi_range_read_info_const(
param->table->pos_in_table_list, keynr, &range_iter, rows, cost,
&range->max_index_blocks, &range->max_row_blocks);
}

/* Figure out if the key scan is ROR (returns rows in ROWID order) or not */
enum ha_key_alg key_alg= param->table->key_info[seq.real_keyno].algorithm;
if ((key_alg != HA_KEY_ALG_BTREE) && (key_alg!= HA_KEY_ALG_UNDEF))
Expand Down
Loading