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,
uint elem_size;
Item *pushed_cond= NULL;
handler *new_h2= 0;
THD *thd= current_thd;
DBUG_ENTER("DsMrr_impl::dsmrr_init");
/*
......@@ -332,17 +333,16 @@ int DsMrr_impl::dsmrr_init(handler *h_arg, RANGE_SEQ_IF *seq_funcs,
// psergey2: split the buffer:
/*
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.
if ((mrr_flags & HA_MRR_SINGLE_POINT) &&
*/
if ((mode & HA_MRR_SINGLE_POINT) &&
optimizer_flag(thd, OPTIMIZER_SWITCH_MRR_SORT_KEYS))
{
do_sort_keys= TRUE; // will use key buffer to sort keys;
bool use_key_pointers= test(mrr_flags & HA_MRR_MATERIALIZED_KEYS);
//do_sort_keys= TRUE; // will use key buffer to sort keys;
use_key_pointers= test(mode & HA_MRR_MATERIALIZED_KEYS);
}
/*
do_rowid_fetch= FALSE;
if (!doing_cpk_scan && !index_only_read)
{
......@@ -409,7 +409,6 @@ int DsMrr_impl::dsmrr_init(handler *h_arg, RANGE_SEQ_IF *seq_funcs,
if (!h2)
{
/* 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.
The constant 5 is an empiric result.
......@@ -609,6 +608,8 @@ int DsMrr_impl::dsmrr_fill_rowid_buffer()
/*
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)
......@@ -617,6 +618,14 @@ int DsMrr_impl::key_tuple_cmp(void* arg, uchar* key1, uchar* key2)
TABLE *table= dsmrr->h->table;
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;
while (key1 < key1_end)
......@@ -664,14 +673,15 @@ void DsMrr_impl::dsmrr_fill_key_buffer()
!(res= h->mrr_funcs.next(h->mrr_iter, &cur_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)
{
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 ==
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_end= mrr_buf_last;
}
......@@ -679,8 +689,12 @@ void DsMrr_impl::dsmrr_fill_key_buffer()
//psergey2: if keys are materialized, store pointers, not copy keys
/* Put key, or {key, range_id} pair into the buffer */
memcpy(mrr_buf_cur, cur_range.start_key.key, cpk_tuple_length);
mrr_buf_cur += cpk_tuple_length;
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);
mrr_buf_cur += key_buf_element_size;
if (is_mrr_assoc)
{
......@@ -692,7 +706,7 @@ void DsMrr_impl::dsmrr_fill_key_buffer()
dsmrr_eof= test(res);
/* 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;
my_qsort2(mrr_buf, n_rowids, elem_size,
......@@ -739,7 +753,8 @@ int DsMrr_impl::dsmrr_next_cpk(char **range_info)
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 &&
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)
}
/* Ok, got the range. Try making a lookup. */
uchar *lookup_tuple= mrr_buf_cur;
mrr_buf_cur += cpk_tuple_length;
uchar *lookup_tuple= use_key_pointers? (*((uchar**)mrr_buf_cur)) : mrr_buf_cur;
mrr_buf_cur += key_buf_element_size;
if (is_mrr_assoc)
{
memcpy(&cpk_saved_range_info, mrr_buf_cur, sizeof(void*));
......
......@@ -115,6 +115,7 @@ private:
uchar *mrr_buf_end; /* End of the buffer */
uchar *mrr_buf_next_identical;
bool use_key_pointers;
bool dsmrr_eof; /* TRUE <=> We have reached EOF when reading index tuples */
......@@ -129,6 +130,8 @@ private:
/* Length of lookup tuple being used, in bytes */
uint cpk_tuple_length;
uint key_buf_element_size;
/*
TRUE <=> We're scanning on a full primary key (and not on prefix), and so
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