List:Commits« Previous MessageNext Message »
From:Sergey Petrunia Date:January 12 2006 7:48am
Subject:bk commit into 5.0 tree (sergefp:1.2027) BUG#16166
View as plain text  
Below is the list of changes that have just been committed into a local
5.0 repository of psergey. When psergey does a push these changes will
be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html

ChangeSet
  1.2027 06/01/12 10:48:27 sergefp@stripped +3 -0
  BUG#16166, "Can't use index_merge with FORCE INDEX": adjust the heurstics check to take into
  account that "FORCE INDEX" disables full table scans, and not range/index_merge scans.
  (with post-review fixes)

  sql/sql_select.cc
    1.381 06/01/12 10:48:14 sergefp@stripped +28 -7
    BUG#16166: "Can't use index_merge with FORCE INDEX": adjust the heuristics check:
    if (force-index-is-used && there-is-possible-ref-access && 
    +    THERE IS NO POSSIBLE RANGE/INDEX_MERGE ACCESS)
    {
      ...

  mysql-test/t/index_merge.test
    1.13 06/01/12 10:48:13 sergefp@stripped +30 -0
    Testcase for BUG#16166

  mysql-test/r/index_merge.result
    1.18 06/01/12 10:48:13 sergefp@stripped +18 -0
    Testcase for BUG#16166

# This is a BitKeeper patch.  What follows are the unified diffs for the
# set of deltas contained in the patch.  The rest of the patch, the part
# that BitKeeper cares about, is below these diffs.
# User:	sergefp
# Host:	newbox.mylan
# Root:	/home/psergey/mysql-5.0-bug16166-r2

--- 1.380/sql/sql_select.cc	2006-01-10 08:44:32 +03:00
+++ 1.381/sql/sql_select.cc	2006-01-12 10:48:14 +03:00
@@ -3471,13 +3471,32 @@
     parts of the row from any of the used index.
     This is because table scans uses index and we would not win
     anything by using a table scan.
+
+    A word for word translation of the below if-statement in psergey's
+    understanding: we check if we should use table scan if:
+    (1) The found 'ref' access produces more records than a table scan
+        (or index scan, or quick select), or 'ref' is more expensive than
+        any of them.
+    (2) This doesn't hold: the best way to perform table scan is to to perform
+        'range' access using index IDX, and the best way to perform 'ref' 
+        access is to use the same index IDX, with the same or more key parts.
+        (note: it is not clear how this rule is/should be extended to 
+        index_merge quick selects)
+    (3) See above note about InnoDB.
+    (4) NOT ("FORCE INDEX(...)" is used for table and there is 'ref' access
+             path, but there is no quick select)
+        If the condition in the above brackets holds, then the only possible
+        "table scan" access method is ALL/index (there is no quick select).
+        Since we have a 'ref' access path, and FORCE INDEX instructs us to
+        choose it over ALL/index, there is no need to consider a full table
+        scan.
   */
-  if ((records >= s->found_records || best > s->read_time) &&
-      !(s->quick && best_key && s->quick->index == best_key->key &&
-        best_max_key_part >= s->table->quick_key_parts[best_key->key]) &&
-      !((s->table->file->table_flags() & HA_TABLE_SCAN_ON_INDEX) &&
-        ! s->table->used_keys.is_clear_all() && best_key) &&
-      !(s->table->force_index && best_key))
+  if ((records >= s->found_records || best > s->read_time) &&            // (1)
+      !(s->quick && best_key && s->quick->index == best_key->key &&      // (2)
+        best_max_key_part >= s->table->quick_key_parts[best_key->key]) &&// (2)
+      !((s->table->file->table_flags() & HA_TABLE_SCAN_ON_INDEX) &&      // (3)
+        ! s->table->used_keys.is_clear_all() && best_key) &&             // (3)
+      !(s->table->force_index && best_key && !s->quick))                 // (4)
   {                                             // Check full join
     ha_rows rnd_records= s->found_records;
     /*
@@ -4460,13 +4479,15 @@
 	parts of the row from any of the used index.
 	This is because table scans uses index and we would not win
 	anything by using a table scan.
+        (see comment in best_access_path() for more details on the below
+         condition)
       */
       if ((records >= s->found_records || best > s->read_time) &&
 	  !(s->quick && best_key && s->quick->index == best_key->key &&
 	    best_max_key_part >= s->table->quick_key_parts[best_key->key]) &&
 	  !((s->table->file->table_flags() & HA_TABLE_SCAN_ON_INDEX) &&
 	    ! s->table->used_keys.is_clear_all() && best_key) &&
-	  !(s->table->force_index && best_key))
+	  !(s->table->force_index && best_key & !s->quick))
       {						// Check full join
         ha_rows rnd_records= s->found_records;
         /*

--- 1.17/mysql-test/r/index_merge.result	2005-10-17 19:08:49 +04:00
+++ 1.18/mysql-test/r/index_merge.result	2006-01-12 10:48:13 +03:00
@@ -384,3 +384,21 @@
 8186
 set join_buffer_size= @save_join_buffer_size;
 drop table t0, t1, t2, t3, t4;
+CREATE TABLE t1 (
+cola char(3) not null, colb char(3) not null,  filler char(200),
+key(cola), key(colb)
+);
+INSERT INTO t1 VALUES ('foo','bar', 'ZZ'),('fuz','baz', 'ZZ');
+OPTIMIZE TABLE t1;
+Table	Op	Msg_type	Msg_text
+test.t1	optimize	status	OK
+select count(*) from t1;
+count(*)
+8704
+explain select * from t1 WHERE cola = 'foo' AND colb = 'bar';
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t1	index_merge	cola,colb	cola,colb	3,3	NULL	24	Using intersect(cola,colb); Using where
+explain select * from t1 force index(cola,colb) WHERE cola = 'foo' AND colb = 'bar';
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t1	index_merge	cola,colb	cola,colb	3,3	NULL	24	Using intersect(cola,colb); Using where
+drop table t1;

--- 1.12/mysql-test/t/index_merge.test	2005-10-17 19:08:53 +04:00
+++ 1.13/mysql-test/t/index_merge.test	2006-01-12 10:48:13 +03:00
@@ -327,3 +327,33 @@
 
 drop table t0, t1, t2, t3, t4;
 
+# BUG#16166
+CREATE TABLE t1 (
+  cola char(3) not null, colb char(3) not null,  filler char(200),
+  key(cola), key(colb)
+);
+INSERT INTO t1 VALUES ('foo','bar', 'ZZ'),('fuz','baz', 'ZZ');
+
+--disable_query_log
+let $1=9;
+while ($1)
+{
+  eval INSERT INTO t1 SELECT * from t1 WHERE cola = 'foo';
+  dec $1;
+}
+
+let $1=13;
+while ($1)
+{
+  eval INSERT INTO t1 SELECT * from t1 WHERE cola <> 'foo';
+  dec $1;
+}
+
+--enable_query_log
+
+OPTIMIZE TABLE t1;
+select count(*) from t1;
+explain select * from t1 WHERE cola = 'foo' AND colb = 'bar';
+explain select * from t1 force index(cola,colb) WHERE cola = 'foo' AND colb = 'bar';
+drop table t1;
+
Thread
bk commit into 5.0 tree (sergefp:1.2027) BUG#16166Sergey Petrunia12 Jan