Commit 7391175d authored by Sergey Petrunya's avatar Sergey Petrunya

DS-MRR support improvements (MWL#123, MWL#124, MWL#125)

- Let DS-MRR/CPK take advantage of materialized keys, when possible
parent e0999cdf
...@@ -312,6 +312,7 @@ int DsMrr_impl::dsmrr_init(handler *h_arg, RANGE_SEQ_IF *seq_funcs, ...@@ -312,6 +312,7 @@ int DsMrr_impl::dsmrr_init(handler *h_arg, RANGE_SEQ_IF *seq_funcs,
uint elem_size; uint elem_size;
Item *pushed_cond= NULL; Item *pushed_cond= NULL;
handler *new_h2= 0; handler *new_h2= 0;
THD *thd= current_thd;
DBUG_ENTER("DsMrr_impl::dsmrr_init"); DBUG_ENTER("DsMrr_impl::dsmrr_init");
/* /*
...@@ -332,17 +333,16 @@ int DsMrr_impl::dsmrr_init(handler *h_arg, RANGE_SEQ_IF *seq_funcs, ...@@ -332,17 +333,16 @@ int DsMrr_impl::dsmrr_init(handler *h_arg, RANGE_SEQ_IF *seq_funcs,
// psergey2: split the buffer: // psergey2: split the buffer:
/* /*
psergey2-note: we can't split the buffer here because we don't know how key psergey2-note: we can't split the buffer here because we don't know how key
length. we'll only be able to do it when we've got the first range. length. we'll only be able to do it when we've got the first range.
*/
if ((mrr_flags & HA_MRR_SINGLE_POINT) && if ((mode & HA_MRR_SINGLE_POINT) &&
optimizer_flag(thd, OPTIMIZER_SWITCH_MRR_SORT_KEYS)) optimizer_flag(thd, OPTIMIZER_SWITCH_MRR_SORT_KEYS))
{ {
do_sort_keys= TRUE; // will use key buffer to sort keys; //do_sort_keys= TRUE; // will use key buffer to sort keys;
bool use_key_pointers= test(mrr_flags & HA_MRR_MATERIALIZED_KEYS); use_key_pointers= test(mode & HA_MRR_MATERIALIZED_KEYS);
} }
/*
do_rowid_fetch= FALSE; do_rowid_fetch= FALSE;
if (!doing_cpk_scan && !index_only_read) if (!doing_cpk_scan && !index_only_read)
{ {
...@@ -409,7 +409,6 @@ int DsMrr_impl::dsmrr_init(handler *h_arg, RANGE_SEQ_IF *seq_funcs, ...@@ -409,7 +409,6 @@ int DsMrr_impl::dsmrr_init(handler *h_arg, RANGE_SEQ_IF *seq_funcs,
if (!h2) if (!h2)
{ {
/* Create a separate handler object to do rnd_pos() calls. */ /* Create a separate handler object to do rnd_pos() calls. */
THD *thd= current_thd;
/* /*
::clone() takes up a lot of stack, especially on 64 bit platforms. ::clone() takes up a lot of stack, especially on 64 bit platforms.
The constant 5 is an empiric result. The constant 5 is an empiric result.
...@@ -609,6 +608,8 @@ int DsMrr_impl::dsmrr_fill_rowid_buffer() ...@@ -609,6 +608,8 @@ int DsMrr_impl::dsmrr_fill_rowid_buffer()
/* /*
my_qsort2-compatible function to compare key tuples my_qsort2-compatible function to compare key tuples
If dsmrr->use_key_pointers==FALSE
*/ */
int DsMrr_impl::key_tuple_cmp(void* arg, uchar* key1, uchar* key2) int DsMrr_impl::key_tuple_cmp(void* arg, uchar* key1, uchar* key2)
...@@ -617,6 +618,14 @@ int DsMrr_impl::key_tuple_cmp(void* arg, uchar* key1, uchar* key2) ...@@ -617,6 +618,14 @@ int DsMrr_impl::key_tuple_cmp(void* arg, uchar* key1, uchar* key2)
TABLE *table= dsmrr->h->table; TABLE *table= dsmrr->h->table;
KEY_PART_INFO *part= table->key_info[table->s->primary_key].key_part; KEY_PART_INFO *part= table->key_info[table->s->primary_key].key_part;
if (dsmrr->use_key_pointers)
{
/* the buffer stores pointers to keys, get to the keys */
key1= *((uchar**)key1);
key2= *((uchar**)key2); // todo is this alignment-safe?
}
uchar *key1_end= key1 + dsmrr->cpk_tuple_length; uchar *key1_end= key1 + dsmrr->cpk_tuple_length;
while (key1 < key1_end) while (key1 < key1_end)
...@@ -664,14 +673,15 @@ void DsMrr_impl::dsmrr_fill_key_buffer() ...@@ -664,14 +673,15 @@ void DsMrr_impl::dsmrr_fill_key_buffer()
!(res= h->mrr_funcs.next(h->mrr_iter, &cur_range))) !(res= h->mrr_funcs.next(h->mrr_iter, &cur_range)))
{ {
DBUG_ASSERT(cur_range.range_flag & EQ_RANGE); DBUG_ASSERT(cur_range.range_flag & EQ_RANGE);
DBUG_ASSERT(!cpk_tuple_length ||
cpk_tuple_length == cur_range.start_key.length);
if (!cpk_tuple_length) if (!cpk_tuple_length)
{ {
cpk_tuple_length= cur_range.start_key.length; cpk_tuple_length= cur_range.start_key.length;
key_buf_element_size= use_key_pointers ? sizeof(char*) :
cpk_tuple_length;
cpk_is_unique_scan= test(table->key_info[h->active_index].key_parts == cpk_is_unique_scan= test(table->key_info[h->active_index].key_parts ==
my_count_bits(cur_range.start_key.keypart_map)); my_count_bits(cur_range.start_key.keypart_map));
uint elem_size= cpk_tuple_length + (int)is_mrr_assoc * sizeof(void*); uint elem_size= key_buf_element_size + (int)is_mrr_assoc * sizeof(void*);
mrr_buf_last= mrr_buf + ((mrr_buf_end - mrr_buf)/elem_size) * elem_size; mrr_buf_last= mrr_buf + ((mrr_buf_end - mrr_buf)/elem_size) * elem_size;
mrr_buf_end= mrr_buf_last; mrr_buf_end= mrr_buf_last;
} }
...@@ -679,8 +689,12 @@ void DsMrr_impl::dsmrr_fill_key_buffer() ...@@ -679,8 +689,12 @@ void DsMrr_impl::dsmrr_fill_key_buffer()
//psergey2: if keys are materialized, store pointers, not copy keys //psergey2: if keys are materialized, store pointers, not copy keys
/* Put key, or {key, range_id} pair into the buffer */ /* Put key, or {key, range_id} pair into the buffer */
if (use_key_pointers)
memcpy(mrr_buf_cur, &cur_range.start_key.key, sizeof(char*));
else
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 += key_buf_element_size;
if (is_mrr_assoc) if (is_mrr_assoc)
{ {
...@@ -692,7 +706,7 @@ void DsMrr_impl::dsmrr_fill_key_buffer() ...@@ -692,7 +706,7 @@ void DsMrr_impl::dsmrr_fill_key_buffer()
dsmrr_eof= test(res); dsmrr_eof= test(res);
/* Sort the buffer contents by rowid */ /* Sort the buffer contents by rowid */
uint elem_size= cpk_tuple_length + (int)is_mrr_assoc * sizeof(void*); uint elem_size= key_buf_element_size + (int)is_mrr_assoc * sizeof(void*);
uint n_rowids= (mrr_buf_cur - mrr_buf) / elem_size; uint n_rowids= (mrr_buf_cur - mrr_buf) / elem_size;
my_qsort2(mrr_buf, n_rowids, elem_size, my_qsort2(mrr_buf, n_rowids, elem_size,
...@@ -739,7 +753,8 @@ int DsMrr_impl::dsmrr_next_cpk(char **range_info) ...@@ -739,7 +753,8 @@ int DsMrr_impl::dsmrr_next_cpk(char **range_info)
break; break;
} }
res= h->index_next_same(table->record[0], mrr_buf_cur, cpk_tuple_length); uchar *lookup_tuple= use_key_pointers? (*((uchar**)mrr_buf_cur)) : mrr_buf_cur;
res= h->index_next_same(table->record[0], lookup_tuple, cpk_tuple_length);
if (h->mrr_funcs.skip_index_tuple && if (h->mrr_funcs.skip_index_tuple &&
h->mrr_funcs.skip_index_tuple(h->mrr_iter, cpk_saved_range_info)) h->mrr_funcs.skip_index_tuple(h->mrr_iter, cpk_saved_range_info))
...@@ -775,8 +790,8 @@ int DsMrr_impl::dsmrr_next_cpk(char **range_info) ...@@ -775,8 +790,8 @@ int DsMrr_impl::dsmrr_next_cpk(char **range_info)
} }
/* 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= use_key_pointers? (*((uchar**)mrr_buf_cur)) : mrr_buf_cur;
mrr_buf_cur += cpk_tuple_length; mrr_buf_cur += key_buf_element_size;
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*));
......
...@@ -115,6 +115,7 @@ private: ...@@ -115,6 +115,7 @@ private:
uchar *mrr_buf_end; /* End of the buffer */ uchar *mrr_buf_end; /* End of the buffer */
uchar *mrr_buf_next_identical; uchar *mrr_buf_next_identical;
bool use_key_pointers;
bool dsmrr_eof; /* TRUE <=> We have reached EOF when reading index tuples */ bool dsmrr_eof; /* TRUE <=> We have reached EOF when reading index tuples */
...@@ -129,6 +130,8 @@ private: ...@@ -129,6 +130,8 @@ private:
/* Length of lookup tuple being used, in bytes */ /* Length of lookup tuple being used, in bytes */
uint cpk_tuple_length; uint cpk_tuple_length;
uint key_buf_element_size;
/* /*
TRUE <=> We're scanning on a full primary key (and not on prefix), and so TRUE <=> We're scanning on a full primary key (and not on prefix), and so
can get max. one match for each key can get max. one match for each key
......
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