Commit b45748f0 authored by Sergey Petrunya's avatar Sergey Petrunya

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
parent 16e197f5
...@@ -128,6 +128,20 @@ a b c filler a b ...@@ -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); ...@@ -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() ...@@ -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;
...@@ -655,6 +654,7 @@ void DsMrr_impl::dsmrr_fill_buffer_cpk() ...@@ -655,6 +654,7 @@ void DsMrr_impl::dsmrr_fill_buffer_cpk()
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) ...@@ -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) ...@@ -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:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment