mirror of
https://github.com/MariaDB/server.git
synced 2025-01-29 10:14:19 +01:00
MWL#121: DS-MRR support for clustered primary keys
- Fix the code to work with IndexConditionPushdown+BKA (EXPLAIN is still incorrect, see comments in the patch) - Test coverage for ICP+BKA
This commit is contained in:
parent
16e197f5b1
commit
b45748f058
3 changed files with 62 additions and 17 deletions
|
@ -128,6 +128,20 @@ a b c filler a b
|
||||||
11 11 12 filler 11 11
|
11 11 12 filler 11 11
|
||||||
11 11 13 filler 11 11
|
11 11 13 filler 11 11
|
||||||
set join_cache_level=6;
|
set join_cache_level=6;
|
||||||
|
explain select * from t1, t2 where t1.a=t2.a and t2.b + t1.b > 100;
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 SIMPLE t2 ALL NULL NULL NULL NULL 3
|
||||||
|
1 SIMPLE t1 ref PRIMARY PRIMARY 4 test.t2.a 1 Using index condition(BKA); Using join buffer
|
||||||
|
select * from t1, t2 where t1.a=t2.a and t2.b + t1.b > 100;
|
||||||
|
a b c filler a b
|
||||||
|
set optimizer_switch='index_condition_pushdown=off';
|
||||||
|
explain select * from t1, t2 where t1.a=t2.a and t2.b + t1.b > 100;
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 SIMPLE t2 ALL NULL NULL NULL NULL 3
|
||||||
|
1 SIMPLE t1 ref PRIMARY PRIMARY 4 test.t2.a 1 Using where; Using join buffer
|
||||||
|
select * from t1, t2 where t1.a=t2.a and t2.b + t1.b > 100;
|
||||||
|
a b c filler a b
|
||||||
|
set optimizer_switch='index_condition_pushdown=on';
|
||||||
drop table t1,t2;
|
drop table t1,t2;
|
||||||
set @@join_cache_level= @save_join_cache_level;
|
set @@join_cache_level= @save_join_cache_level;
|
||||||
set storage_engine=@save_storage_engine;
|
set storage_engine=@save_storage_engine;
|
||||||
|
|
|
@ -112,21 +112,24 @@ insert into t2 values (11,33), (11,22), (11,11);
|
||||||
explain select * from t1, t2 where t1.a=t2.a and t1.b=t2.b;
|
explain select * from t1, t2 where t1.a=t2.a and t1.b=t2.b;
|
||||||
select * from t1, t2 where t1.a=t2.a and t1.b=t2.b;
|
select * from t1, t2 where t1.a=t2.a and t1.b=t2.b;
|
||||||
|
|
||||||
|
# Check a real resultset for comaprison:
|
||||||
set join_cache_level=0;
|
set join_cache_level=0;
|
||||||
select * from t1, t2 where t1.a=t2.a and t1.b=t2.b;
|
select * from t1, t2 where t1.a=t2.a and t1.b=t2.b;
|
||||||
set join_cache_level=6;
|
set join_cache_level=6;
|
||||||
|
|
||||||
drop table t1,t2;
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Check that Index Condition Pushdown (BKA) actually works:
|
# Check that Index Condition Pushdown (BKA) actually works:
|
||||||
#
|
#
|
||||||
|
explain select * from t1, t2 where t1.a=t2.a and t2.b + t1.b > 100;
|
||||||
|
select * from t1, t2 where t1.a=t2.a and t2.b + t1.b > 100;
|
||||||
|
|
||||||
# TODO
|
set optimizer_switch='index_condition_pushdown=off';
|
||||||
|
explain select * from t1, t2 where t1.a=t2.a and t2.b + t1.b > 100;
|
||||||
|
select * from t1, t2 where t1.a=t2.a and t2.b + t1.b > 100;
|
||||||
|
set optimizer_switch='index_condition_pushdown=on';
|
||||||
|
|
||||||
#
|
drop table t1,t2;
|
||||||
# Check that record-check-func is done:
|
|
||||||
#
|
|
||||||
|
|
||||||
set @@join_cache_level= @save_join_cache_level;
|
set @@join_cache_level= @save_join_cache_level;
|
||||||
set storage_engine=@save_storage_engine;
|
set storage_engine=@save_storage_engine;
|
||||||
|
|
|
@ -624,7 +624,6 @@ void DsMrr_impl::dsmrr_fill_buffer_cpk()
|
||||||
{
|
{
|
||||||
DBUG_ASSERT(cur_range.range_flag & EQ_RANGE);
|
DBUG_ASSERT(cur_range.range_flag & EQ_RANGE);
|
||||||
DBUG_ASSERT(cpk_tuple_length == cur_range.start_key.length);
|
DBUG_ASSERT(cpk_tuple_length == cur_range.start_key.length);
|
||||||
|
|
||||||
/* Put key, or {key, range_id} pair into the buffer */
|
/* Put key, or {key, range_id} pair into the buffer */
|
||||||
memcpy(mrr_buf_cur, cur_range.start_key.key, cpk_tuple_length);
|
memcpy(mrr_buf_cur, cur_range.start_key.key, cpk_tuple_length);
|
||||||
mrr_buf_cur += cpk_tuple_length;
|
mrr_buf_cur += cpk_tuple_length;
|
||||||
|
@ -654,7 +653,8 @@ void DsMrr_impl::dsmrr_fill_buffer_cpk()
|
||||||
DS-MRR/CPK: multi_range_read_next() function
|
DS-MRR/CPK: multi_range_read_next() function
|
||||||
|
|
||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
DsMrr_impl::dsmrr_next_cpk()
|
DsMrr_impl::dsmrr_next_cpk()
|
||||||
|
range_info OUT identifier of range that the returned record belongs to
|
||||||
|
|
||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
DS-MRR/CPK: multi_range_read_next() function.
|
DS-MRR/CPK: multi_range_read_next() function.
|
||||||
|
@ -673,16 +673,31 @@ int DsMrr_impl::dsmrr_next_cpk(char **range_info)
|
||||||
{
|
{
|
||||||
int res;
|
int res;
|
||||||
|
|
||||||
if (cpk_have_range)
|
while (cpk_have_range)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
if (h->mrr_funcs.skip_record &&
|
||||||
|
h->mrr_funcs.skip_record(h->mrr_iter, cpk_saved_range_info, NULL))
|
||||||
|
{
|
||||||
|
cpk_have_range= FALSE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
res= h->index_next_same(table->record[0], mrr_buf_cur, cpk_tuple_length);
|
res= h->index_next_same(table->record[0], mrr_buf_cur, cpk_tuple_length);
|
||||||
|
|
||||||
|
if (h->mrr_funcs.skip_index_tuple &&
|
||||||
|
h->mrr_funcs.skip_index_tuple(h->mrr_iter, cpk_saved_range_info))
|
||||||
|
continue;
|
||||||
|
|
||||||
if (res != HA_ERR_END_OF_FILE)
|
if (res != HA_ERR_END_OF_FILE)
|
||||||
{
|
{
|
||||||
if (is_mrr_assoc)
|
if (is_mrr_assoc)
|
||||||
memcpy(range_info, &cpk_saved_range_info, sizeof(void*));
|
memcpy(range_info, &cpk_saved_range_info, sizeof(void*));
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
/* No more records in this range. Fall through to get to another range */
|
|
||||||
|
/* No more records in this range. Exit this loop and go get another range */
|
||||||
|
cpk_have_range= FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
do
|
do
|
||||||
|
@ -703,30 +718,43 @@ int DsMrr_impl::dsmrr_next_cpk(char **range_info)
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
||||||
//psergey2-todo: make skip_index_tuple() calls, too?
|
|
||||||
//psergey2-todo: skip-record calls here?
|
|
||||||
//if (h2->mrr_funcs.skip_record &&
|
|
||||||
// h2->mrr_funcs.skip_record(h2->mrr_iter, (char *) cur_range_info, rowid))
|
|
||||||
// continue;
|
|
||||||
|
|
||||||
/* Ok, got the range. Try making a lookup. */
|
/* Ok, got the range. Try making a lookup. */
|
||||||
uchar *lookup_tuple= mrr_buf_cur;
|
uchar *lookup_tuple= mrr_buf_cur;
|
||||||
mrr_buf_cur += cpk_tuple_length;
|
mrr_buf_cur += cpk_tuple_length;
|
||||||
if (is_mrr_assoc)
|
if (is_mrr_assoc)
|
||||||
{
|
{
|
||||||
memcpy(cpk_saved_range_info, mrr_buf_cur, sizeof(void*));
|
memcpy(&cpk_saved_range_info, mrr_buf_cur, sizeof(void*));
|
||||||
mrr_buf_cur += sizeof(void*) * test(is_mrr_assoc);
|
mrr_buf_cur += sizeof(void*) * test(is_mrr_assoc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (h->mrr_funcs.skip_record &&
|
||||||
|
h->mrr_funcs.skip_record(h->mrr_iter, cpk_saved_range_info, NULL))
|
||||||
|
continue;
|
||||||
|
|
||||||
res= h->index_read(table->record[0], lookup_tuple, cpk_tuple_length,
|
res= h->index_read(table->record[0], lookup_tuple, cpk_tuple_length,
|
||||||
HA_READ_KEY_EXACT);
|
HA_READ_KEY_EXACT);
|
||||||
|
|
||||||
|
/*
|
||||||
|
Check pushed index condition. Performance-wise, it does not make any
|
||||||
|
sense to put this call here (the above call has already accessed the full
|
||||||
|
record). That's the best I could do, though, because:
|
||||||
|
- ha_innobase doesn't support IndexConditionPushdown on clustered PK
|
||||||
|
- MRR interface doesn't allow the storage engine to refuse a pushed index
|
||||||
|
condition.
|
||||||
|
Having this call here is not fully harmless: EXPLAIN shows "pushed index
|
||||||
|
condition", which is technically true but doesn't bring the benefits that
|
||||||
|
one might expect.
|
||||||
|
*/
|
||||||
|
if (h->mrr_funcs.skip_index_tuple &&
|
||||||
|
h->mrr_funcs.skip_index_tuple(h->mrr_iter, cpk_saved_range_info))
|
||||||
|
continue;
|
||||||
|
|
||||||
if (res && res != HA_ERR_END_OF_FILE)
|
if (res && res != HA_ERR_END_OF_FILE)
|
||||||
goto end;
|
goto end;
|
||||||
|
|
||||||
if (!res)
|
if (!res)
|
||||||
{
|
{
|
||||||
memcpy(range_info, cpk_saved_range_info, sizeof(void*));
|
memcpy(range_info, &cpk_saved_range_info, sizeof(void*));
|
||||||
/*
|
/*
|
||||||
Attempt reading more rows from this range only if there actually can
|
Attempt reading more rows from this range only if there actually can
|
||||||
be multiple matches:
|
be multiple matches:
|
||||||
|
|
Loading…
Add table
Reference in a new issue