[Commits] Rev 2806: DS-MRR support improvements (MWL#123, MWL#124, MWL#125) in file:///home/psergey/dev2/maria-5.3-dsmrr-cpk-r2/

Sergey Petrunya psergey at askmonty.org
Sat Jul 17 17:03:53 EEST 2010


At file:///home/psergey/dev2/maria-5.3-dsmrr-cpk-r2/

------------------------------------------------------------
revno: 2806
revision-id: psergey at askmonty.org-20100717140350-fpj0q8rijfy1by6y
parent: psergey at askmonty.org-20100716093823-ukg6o5oslz42yoy0
committer: Sergey Petrunya <psergey at askmonty.org>
branch nick: maria-5.3-dsmrr-cpk-r2
timestamp: Sat 2010-07-17 18:03:50 +0400
message:
  DS-MRR support improvements (MWL#123, MWL#124, MWL#125)
  - Lots of TODO comments
  - add mrr_sort_keys flag to @@optimizer_switch
  - [from Igor] SQL layer part passes HA_MRR_MATERIALIZED_KEYS flag
  - Don't call rnd_pos() many times in a row if sorted rowid buffer
    has the same rowid value for multiple consequive (rowid, range_id) pairs.
=== modified file 'mysql-test/r/optimizer_switch.result'
--- a/mysql-test/r/optimizer_switch.result	2010-07-16 08:58:24 +0000
+++ b/mysql-test/r/optimizer_switch.result	2010-07-17 14:03:50 +0000
@@ -4,19 +4,19 @@
 #
 select @@optimizer_switch;
 @@optimizer_switch
-index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_condition_pushdown=on,firstmatch=on,loosescan=on,materialization=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on
+index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_condition_pushdown=on,firstmatch=on,loosescan=on,materialization=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr_sort_keys=on
 set optimizer_switch='index_merge=off,index_merge_union=off';
 select @@optimizer_switch;
 @@optimizer_switch
-index_merge=off,index_merge_union=off,index_merge_sort_union=on,index_merge_intersection=on,index_condition_pushdown=on,firstmatch=on,loosescan=on,materialization=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on
+index_merge=off,index_merge_union=off,index_merge_sort_union=on,index_merge_intersection=on,index_condition_pushdown=on,firstmatch=on,loosescan=on,materialization=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr_sort_keys=on
 set optimizer_switch='index_merge_union=on';
 select @@optimizer_switch;
 @@optimizer_switch
-index_merge=off,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_condition_pushdown=on,firstmatch=on,loosescan=on,materialization=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on
+index_merge=off,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_condition_pushdown=on,firstmatch=on,loosescan=on,materialization=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr_sort_keys=on
 set optimizer_switch='default,index_merge_sort_union=off';
 select @@optimizer_switch;
 @@optimizer_switch
-index_merge=on,index_merge_union=on,index_merge_sort_union=off,index_merge_intersection=on,index_condition_pushdown=on,firstmatch=on,loosescan=on,materialization=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on
+index_merge=on,index_merge_union=on,index_merge_sort_union=off,index_merge_intersection=on,index_condition_pushdown=on,firstmatch=on,loosescan=on,materialization=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr_sort_keys=on
 set optimizer_switch=4;
 ERROR 42000: Variable 'optimizer_switch' can't be set to the value of '4'
 set optimizer_switch=NULL;
@@ -43,57 +43,57 @@
 set optimizer_switch='index_merge=off,index_merge_union=off,default';
 select @@optimizer_switch;
 @@optimizer_switch
-index_merge=off,index_merge_union=off,index_merge_sort_union=on,index_merge_intersection=on,index_condition_pushdown=on,firstmatch=on,loosescan=on,materialization=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on
+index_merge=off,index_merge_union=off,index_merge_sort_union=on,index_merge_intersection=on,index_condition_pushdown=on,firstmatch=on,loosescan=on,materialization=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr_sort_keys=on
 set optimizer_switch=default;
 select @@global.optimizer_switch;
 @@global.optimizer_switch
-index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_condition_pushdown=on,firstmatch=on,loosescan=on,materialization=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on
+index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_condition_pushdown=on,firstmatch=on,loosescan=on,materialization=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr_sort_keys=on
 set @@global.optimizer_switch=default;
 select @@global.optimizer_switch;
 @@global.optimizer_switch
-index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_condition_pushdown=on,firstmatch=on,loosescan=on,materialization=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on
+index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_condition_pushdown=on,firstmatch=on,loosescan=on,materialization=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr_sort_keys=on
 #
 # Check index_merge's @@optimizer_switch flags
 #
 select @@optimizer_switch;
 @@optimizer_switch
-index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_condition_pushdown=on,firstmatch=on,loosescan=on,materialization=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on
+index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_condition_pushdown=on,firstmatch=on,loosescan=on,materialization=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr_sort_keys=on
 
 BUG#37120 optimizer_switch allowable values not according to specification
 
 select @@optimizer_switch;
 @@optimizer_switch
-index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_condition_pushdown=on,firstmatch=on,loosescan=on,materialization=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on
+index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_condition_pushdown=on,firstmatch=on,loosescan=on,materialization=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr_sort_keys=on
 set optimizer_switch='default,materialization=off';
 select @@optimizer_switch;
 @@optimizer_switch
-index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_condition_pushdown=on,firstmatch=on,loosescan=on,materialization=off,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on
+index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_condition_pushdown=on,firstmatch=on,loosescan=on,materialization=off,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr_sort_keys=on
 set optimizer_switch='default,semijoin=off';
 select @@optimizer_switch;
 @@optimizer_switch
-index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_condition_pushdown=on,firstmatch=on,loosescan=on,materialization=on,semijoin=off,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on
+index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_condition_pushdown=on,firstmatch=on,loosescan=on,materialization=on,semijoin=off,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr_sort_keys=on
 set optimizer_switch='default,loosescan=off';
 select @@optimizer_switch;
 @@optimizer_switch
-index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_condition_pushdown=on,firstmatch=on,loosescan=off,materialization=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on
+index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_condition_pushdown=on,firstmatch=on,loosescan=off,materialization=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr_sort_keys=on
 set optimizer_switch='default,semijoin=off,materialization=off';
 select @@optimizer_switch;
 @@optimizer_switch
-index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_condition_pushdown=on,firstmatch=on,loosescan=on,materialization=off,semijoin=off,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on
+index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_condition_pushdown=on,firstmatch=on,loosescan=on,materialization=off,semijoin=off,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr_sort_keys=on
 set optimizer_switch='default,materialization=off,semijoin=off';
 select @@optimizer_switch;
 @@optimizer_switch
-index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_condition_pushdown=on,firstmatch=on,loosescan=on,materialization=off,semijoin=off,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on
+index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_condition_pushdown=on,firstmatch=on,loosescan=on,materialization=off,semijoin=off,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr_sort_keys=on
 set optimizer_switch='default,semijoin=off,materialization=off,loosescan=off';
 select @@optimizer_switch;
 @@optimizer_switch
-index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_condition_pushdown=on,firstmatch=on,loosescan=off,materialization=off,semijoin=off,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on
+index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_condition_pushdown=on,firstmatch=on,loosescan=off,materialization=off,semijoin=off,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr_sort_keys=on
 set optimizer_switch='default,semijoin=off,loosescan=off';
 select @@optimizer_switch;
 @@optimizer_switch
-index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_condition_pushdown=on,firstmatch=on,loosescan=off,materialization=on,semijoin=off,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on
+index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_condition_pushdown=on,firstmatch=on,loosescan=off,materialization=on,semijoin=off,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr_sort_keys=on
 set optimizer_switch='default,materialization=off,loosescan=off';
 select @@optimizer_switch;
 @@optimizer_switch
-index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_condition_pushdown=on,firstmatch=on,loosescan=off,materialization=off,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on
+index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_condition_pushdown=on,firstmatch=on,loosescan=off,materialization=off,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr_sort_keys=on
 set optimizer_switch=default;

=== modified file 'sql/handler.h'
--- a/sql/handler.h	2010-07-16 09:38:23 +0000
+++ b/sql/handler.h	2010-07-17 14:03:50 +0000
@@ -1322,6 +1322,12 @@
 */
 #define HA_MRR_NO_NULL_ENDPOINTS 128
 
+/*
+  The MRR user has materialized range keys somewhere in the user's buffer.
+  This can be used for optimization of the procedure that sorts these keys
+  since in this case key values don't have to be copied into the MRR buffer.
+*/
+#define HA_MRR_MATERIALIZED_KEYS 256
 
 
 /*

=== modified file 'sql/multi_range_read.cc'
--- a/sql/multi_range_read.cc	2010-07-16 09:38:23 +0000
+++ b/sql/multi_range_read.cc	2010-07-17 14:03:50 +0000
@@ -327,24 +327,62 @@
                                         mode, buf);
     DBUG_RETURN(retval);
   }
+  use_default_impl= FALSE;
+  is_mrr_assoc= !test(mode & HA_MRR_NO_ASSOCIATION);
+
+  // 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) && 
+       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_rowid_fetch= FALSE;
+  if (!doing_cpk_scan && !index_only_read)
+  {
+    do_rowid_fetch= TRUE; //will use rowid buffer to store/sort rowids, etc
+  }
+
+
+  if (do_sort_keys && do_rowid_fetch)
+  {
+    split buffer space proportionally
+  }
+  else
+  {
+    // give all space to one buffer
+    if (do_sort_keys)
+    {
+      //sort_buffer_start= ...;
+    }
+    else 
+    {
+      DBUG_ASSERT(do_rowid_fetch);
+      //rowid_buffer_start= ...;
+    }
+  }
+  */
   mrr_buf= buf->buffer;
-
-  is_mrr_assoc= !test(mode & HA_MRR_NO_ASSOCIATION);
+  mrr_buf_end= buf->buffer_end;
 
   if (is_mrr_assoc)
     status_var_increment(table->in_use->status_var.ha_multi_range_read_init_count);
- 
-  mrr_buf_end= buf->buffer_end;
 
   if ((doing_cpk_scan= check_cpk_scan(h->active_index, mode)))
   {
     /* It's a DS-MRR/CPK scan */
     cpk_tuple_length= 0; /* dummy value telling it needs to be inited */
     cpk_have_range= FALSE;
-    use_default_impl= FALSE;
     h->mrr_iter= seq_funcs->init(seq_init_param, n_ranges, mode);
     h->mrr_funcs= *seq_funcs;
-    dsmrr_fill_buffer_cpk();
+    dsmrr_fill_key_buffer();
+    
     if (dsmrr_eof)
       buf->end_of_used_area= mrr_buf_last;
     DBUG_RETURN(0); /* nothing could go wrong while filling the buffer */
@@ -356,6 +394,11 @@
   mrr_buf_end= mrr_buf_last;
 
   /*
+    psergey2: this is only needed when 
+      - doing a rowid-to-row scan
+      - the buffer wasn't exhausted on the first pass.
+  */
+  /*
     There can be two cases:
     - This is the first call since index_init(), h2==NULL
        Need to setup h2 then.
@@ -365,7 +408,7 @@
   */
   if (!h2)
   {
-    /* Create a separate handler object to do rndpos() 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.
@@ -376,7 +419,7 @@
     DBUG_ASSERT(h->active_index != MAX_KEY);
     uint mrr_keyno= h->active_index;
 
-    /* Create a separate handler object to do rndpos() calls. */
+    /* Create a separate handler object to do rnd_pos() calls. */
     if (!(new_h2= h->clone(thd->mem_root)) || 
         new_h2->ha_external_lock(thd, F_RDLCK))
     {
@@ -397,6 +440,7 @@
       goto error;
     }
 
+    use_default_impl= FALSE;
     h2= new_h2; /* Ok, now can put it into h2 */
     table->prepare_for_position();
     h2->extra(HA_EXTRA_KEYREAD);
@@ -404,7 +448,6 @@
     if (h2->ha_index_init(mrr_keyno, FALSE))
       goto error;
 
-    use_default_impl= FALSE;
     if (pushed_cond)
       h2->idx_cond_push(mrr_keyno, pushed_cond);
   }
@@ -422,14 +465,13 @@
     h2= NULL;
     int res= (h->inited == handler::INDEX && h->ha_index_end());
     h2= save_h2;
-    use_default_impl= FALSE;
     if (res)
       goto error;
   }
 
   if (h2->handler::multi_range_read_init(seq_funcs, seq_init_param, n_ranges, 
                                          mode, buf) ||
-      dsmrr_fill_buffer())
+      dsmrr_fill_rowid_buffer())
   {
     goto error;
   }
@@ -449,7 +491,6 @@
        (h->ha_rnd_init(FALSE))))
       goto error;
 
-  use_default_impl= FALSE;
   h->mrr_funcs= *seq_funcs;
   
   DBUG_RETURN(0);
@@ -497,6 +538,9 @@
 
   dsmrr_eof is set to indicate whether we've exhausted the list of ranges we're
   scanning.
+
+  psergey2: this func will 'fill the rowid buffer'. If filling the rowid buffer 
+  requires that key buffer is filled/sorted first, will do that, too.
   
   @param h  Table handler
 
@@ -505,13 +549,27 @@
   @retval other  Error
 */
 
-int DsMrr_impl::dsmrr_fill_buffer()
+int DsMrr_impl::dsmrr_fill_rowid_buffer()
 {
   char *range_info;
   int res;
-  DBUG_ENTER("DsMrr_impl::dsmrr_fill_buffer");
+  DBUG_ENTER("DsMrr_impl::dsmrr_fill_rowid_buffer");
+  
+  mrr_buf_cur= mrr_buf;
+  mrr_buf_next_identical= mrr_buf_cur;
+  /*
+    psergey2-todo:
+      - call here fill/sort key buffer, if needed.
 
-  mrr_buf_cur= mrr_buf;
+    psergey2-todo: then, get keys either from
+      - multi_range_read_next()
+      - sorted key buffer
+    
+    psergey2-todo: if we're traversing an ordered key sequence,
+     check if next keys are the same as previous.
+     (note that it's easy as ordered sequence allows forward/backward
+     navigation so we don't need to buffer things)
+  */
   while ((mrr_buf_cur < mrr_buf_end) && 
          !(res= h2->handler::multi_range_read_next(&range_info)))
   {
@@ -520,6 +578,7 @@
         h2->mrr_funcs.skip_index_tuple(h2->mrr_iter, curr_range->ptr))
       continue;
     
+
     /* Put rowid, or {rowid, range_id} pair into the buffer */
     h2->position(table->record[0]);
     memcpy(mrr_buf_cur, h2->ref, h2->ref_length);
@@ -579,20 +638,26 @@
   DS-MRR/CPK: Fill the buffer with (lookup_tuple, range_id) pairs and sort
   
   SYNOPSIS
-    DsMrr_impl::dsmrr_fill_buffer_cpk()
+    DsMrr_impl::dsmrr_fill_key_buffer()
 
   DESCRIPTION
     DS-MRR/CPK: Fill the buffer with (lookup_tuple, range_id) pairs and sort
 
     dsmrr_eof is set to indicate whether we've exhausted the list of ranges 
     we're scanning.
+
+  psergey2-q: can this be used for filling/sorting key buffer in general case?
+   a: yes. 
+  qq: can we push sequence iteration init down into here?
 */
 
-void DsMrr_impl::dsmrr_fill_buffer_cpk()
+void DsMrr_impl::dsmrr_fill_key_buffer()
 {
+  //psergey2: here, no identicals detection is necessary since we always scan
+  //  the unordered sequence.
   int res;
   KEY_MULTI_RANGE cur_range;
-  DBUG_ENTER("DsMrr_impl::dsmrr_fill_buffer_cpk");
+  DBUG_ENTER("DsMrr_impl::dsmrr_fill_key_buffer");
 
   mrr_buf_cur= mrr_buf;
   while ((mrr_buf_cur < mrr_buf_end) && 
@@ -611,6 +676,8 @@
       mrr_buf_end= mrr_buf_last;
     }
 
+    //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;
@@ -648,12 +715,14 @@
     This is similar to DsMrr_impl::dsmrr_next(), the differences are that
      - we get records with index_read(), not with rnd_pos()
      - we may get multiple records for one key (=element of the buffer)
-     - unlike dsmrr_fill_buffer(), dsmrr_fill_buffer_cpk() never fails.
+     - unlike dsmrr_fill_rowid_buffer(), dsmrr_fill_key_buffer() never fails.
  
   RETURN
     0                   OK, next record was successfully read
     HA_ERR_END_OF_FILE  End of records
     Other               Some other error
+
+  psergey2-todo: this should detect identical keys.
 */
 
 int DsMrr_impl::dsmrr_next_cpk(char **range_info)
@@ -697,7 +766,7 @@
         res= HA_ERR_END_OF_FILE;
         goto end;
       }
-      dsmrr_fill_buffer_cpk();
+      dsmrr_fill_key_buffer();
     }
     if (mrr_buf_cur == mrr_buf_last)
     {
@@ -758,6 +827,9 @@
 
 /**
   DS-MRR implementation: multi_range_read_next() function
+
+  psergey2-todo: put identical rowid detection code here
+    it should always work because rowid sequences are always sorted
 */
 
 int DsMrr_impl::dsmrr_next(char **range_info)
@@ -772,6 +844,23 @@
   if (doing_cpk_scan)
     return dsmrr_next_cpk(range_info);
   
+  if (mrr_buf_next_identical != mrr_buf_cur)
+  {
+    /*
+      There are multiple rowids. Return the record again, now with different
+      range_id 
+    */
+    do 
+    {
+      if (is_mrr_assoc)
+        memcpy(range_info, mrr_buf_next_identical + h->ref_length, sizeof(uchar*));
+    } while (!h2->mrr_funcs.skip_record ||
+             !h2->mrr_funcs.skip_record(h2->mrr_iter, (char *) range_info, rowid));
+
+    mrr_buf_next_identical += h->ref_length + sizeof(void*) * test(is_mrr_assoc);
+    return 0;
+  }
+
   do
   {
     if (mrr_buf_cur == mrr_buf_last)
@@ -781,7 +870,7 @@
         res= HA_ERR_END_OF_FILE;
         goto end;
       }
-      res= dsmrr_fill_buffer();
+      res= dsmrr_fill_rowid_buffer();
       if (res)
         goto end;
     }
@@ -796,13 +885,34 @@
 
     if (is_mrr_assoc)
       memcpy(&cur_range_info, mrr_buf_cur + h->ref_length, sizeof(uchar**));
+    
+    size_t element_size= h->ref_length + sizeof(void*) * test(is_mrr_assoc);
+    mrr_buf_cur += element_size;
+    mrr_buf_next_identical= mrr_buf_cur;
 
-    mrr_buf_cur += h->ref_length + sizeof(void*) * test(is_mrr_assoc);
     if (h2->mrr_funcs.skip_record &&
 	h2->mrr_funcs.skip_record(h2->mrr_iter, (char *) cur_range_info, rowid))
       continue;
     res= h->ha_rnd_pos(table->record[0], rowid);
+
+    if (res == HA_ERR_RECORD_DELETED)
+      continue;
+    
+    if (0)//(!res)
+    {
+      /* 
+        Note: this implies that SQL layer doesn't touch table->record[0]
+        between calls.
+      */
+      uchar *current_el= mrr_buf_cur - element_size;
+      while (mrr_buf_cur != mrr_buf_last && 
+             !h2->cmp_ref(current_el, mrr_buf_cur))
+      {
+        mrr_buf_cur += element_size;
+      }
+    }
     break;
+
   } while (true);
  
   if (is_mrr_assoc)
@@ -986,7 +1096,7 @@
     *flags |= HA_MRR_USE_DEFAULT_IMPL;
     return TRUE;
   }
-  
+
   uint add_len= table->key_info[keyno].key_length + h->ref_length; 
   *bufsz -= add_len;
   if (get_disk_sweep_mrr_cost(keyno, rows, *flags, bufsz, &dsmrr_cost))
@@ -1010,6 +1120,10 @@
     *flags &= ~HA_MRR_SORTED;          /* We will return unordered output */
     *cost= dsmrr_cost;
     res= FALSE;
+
+    if ((*flags & HA_MRR_SINGLE_POINT) && 
+         optimizer_flag(thd, OPTIMIZER_SWITCH_MRR_SORT_KEYS))
+      *flags |= HA_MRR_MATERIALIZED_KEYS;
   }
   else
   {

=== modified file 'sql/multi_range_read.h'
--- a/sql/multi_range_read.h	2010-06-22 19:26:11 +0000
+++ b/sql/multi_range_read.h	2010-07-17 14:03:50 +0000
@@ -114,6 +114,8 @@
   uchar *mrr_buf_last;  /* When reading: end of used buffer space */
   uchar *mrr_buf_end;   /* End of the buffer */
 
+  uchar *mrr_buf_next_identical;
+
   bool dsmrr_eof; /* TRUE <=> We have reached EOF when reading index tuples */
 
   /* TRUE <=> need range association, buffer holds {rowid, range_id} pairs */
@@ -143,8 +145,8 @@
                                uint *buffer_size, COST_VECT *cost);
   bool check_cpk_scan(uint keyno, uint mrr_flags);
   static int key_tuple_cmp(void* arg, uchar* key1, uchar* key2);
-  int dsmrr_fill_buffer();
-  void dsmrr_fill_buffer_cpk();
+  int dsmrr_fill_rowid_buffer();
+  void dsmrr_fill_key_buffer();
   int dsmrr_next_cpk(char **range_info);
 };
 

=== modified file 'sql/mysql_priv.h'
--- a/sql/mysql_priv.h	2010-07-10 10:37:30 +0000
+++ b/sql/mysql_priv.h	2010-07-17 14:03:50 +0000
@@ -571,12 +571,13 @@
 #define OPTIMIZER_SWITCH_PARTIAL_MATCH_ROWID_MERGE 512
 #define OPTIMIZER_SWITCH_PARTIAL_MATCH_TABLE_SCAN 1024
 #define OPTIMIZER_SWITCH_SUBQUERY_CACHE (1<<11)
+#define OPTIMIZER_SWITCH_MRR_SORT_KEYS (1<<12)
 
 #ifdef DBUG_OFF
-#  define OPTIMIZER_SWITCH_LAST (1<<12)
-#else
-#  define OPTIMIZER_SWITCH_TABLE_ELIMINATION (1<<12)
 #  define OPTIMIZER_SWITCH_LAST (1<<13)
+#else
+#  define OPTIMIZER_SWITCH_TABLE_ELIMINATION (1<<13)
+#  define OPTIMIZER_SWITCH_LAST (1<<14)
 #endif
 
 #ifdef DBUG_OFF 
@@ -592,7 +593,8 @@
                                     OPTIMIZER_SWITCH_SEMIJOIN | \
                                     OPTIMIZER_SWITCH_PARTIAL_MATCH_ROWID_MERGE|\
                                     OPTIMIZER_SWITCH_PARTIAL_MATCH_TABLE_SCAN|\
-                                    OPTIMIZER_SWITCH_SUBQUERY_CACHE)
+                                    OPTIMIZER_SWITCH_SUBQUERY_CACHE|\
+                                    OPTIMIZER_SWITCH_MRR_SORT_KEYS)
 #else
 #  define OPTIMIZER_SWITCH_DEFAULT (OPTIMIZER_SWITCH_INDEX_MERGE | \
                                     OPTIMIZER_SWITCH_INDEX_MERGE_UNION | \
@@ -606,7 +608,8 @@
                                     OPTIMIZER_SWITCH_SEMIJOIN | \
                                     OPTIMIZER_SWITCH_PARTIAL_MATCH_ROWID_MERGE|\
                                     OPTIMIZER_SWITCH_PARTIAL_MATCH_TABLE_SCAN|\
-                                    OPTIMIZER_SWITCH_SUBQUERY_CACHE)
+                                    OPTIMIZER_SWITCH_SUBQUERY_CACHE|\
+                                    OPTIMIZER_SWITCH_MRR_SORT_KEYS)
 #endif
 
 /*

=== modified file 'sql/mysqld.cc'
--- a/sql/mysqld.cc	2010-07-16 08:58:24 +0000
+++ b/sql/mysqld.cc	2010-07-17 14:03:50 +0000
@@ -308,6 +308,7 @@
   "partial_match_rowid_merge",
   "partial_match_table_scan",
   "subquery_cache",
+  "mrr_sort_keys",
 #ifndef DBUG_OFF
   "table_elimination",
 #endif
@@ -329,6 +330,7 @@
   sizeof("partial_match_rowid_merge") - 1,
   sizeof("partial_match_table_scan") - 1,
   sizeof("subquery_cache") - 1,
+  sizeof("mrr_sort_keys") - 1,
 #ifndef DBUG_OFF
   sizeof("table_elimination") - 1,
 #endif
@@ -415,7 +417,8 @@
                                         "semijoin=on,"
                                         "partial_match_rowid_merge=on,"
                                         "partial_match_table_scan=on,"
-                                        "subquery_cache=on"
+                                        "subquery_cache=on,"
+                                        "mrr_sort_keys=on"
 #ifndef DBUG_OFF
                                         ",table_elimination=on";
 #else

=== modified file 'sql/sql_join_cache.cc'
--- a/sql/sql_join_cache.cc	2010-07-16 09:38:23 +0000
+++ b/sql/sql_join_cache.cc	2010-07-17 14:03:50 +0000
@@ -651,6 +651,9 @@
 
   use_emb_key= check_emb_key_usage();
 
+  if (use_emb_key)
+    mrr_mode|= HA_MRR_MATERIALIZED_KEYS;
+
   create_remaining_fields(FALSE);
 
   set_constants();
@@ -2631,6 +2634,8 @@
       data_fields_offset+= copy->length;
   } 
 
+  mrr_mode|= HA_MRR_MATERIALIZED_KEYS;
+
   DBUG_RETURN(rc);
 }
 



More information about the commits mailing list