List:Commits« Previous MessageNext Message »
From:Sergey Glukhov Date:October 27 2011 8:41am
Subject:bzr push into mysql-trunk branch (sergey.glukhov:3533 to 3534) Bug#11747423
View as plain text  
 3534 Sergey Glukhov	2011-10-27
      Bug#11747423 32254: INDEX MERGE USED UNNECESSARILY
      There was an assumption that quick select is always faster
      than ref access for InnoDB tables. But some test cases show
      that it's not true for index merge access. In some cases
      ref access by compound single key is better than
      index merge access by several keys. The fix is to
      add a check that INDEX MERGE access is not more expensive
      than ref access.
     @ mysql-test/r/index_merge_innodb.result
        test case
     @ mysql-test/t/index_merge_innodb.test
        test case
     @ sql/sql_select.cc
        added a check that INDEX MERGE access is not more expensive
        than ref access.

    modified:
      mysql-test/r/index_merge_innodb.result
      mysql-test/t/index_merge_innodb.test
      sql/sql_select.cc
 3533 Jimmy Yang	2011-10-27
      Fix Bug #11755924 - 47764: PARTITIONED INNODB TABLES CAN'T BE MOVED DIRECTLY
      FROM WINDOWS TO LINUX
                              
      rb://786 approved by Sunny Bains

    modified:
      storage/innobase/handler/ha_innodb.cc
=== modified file 'mysql-test/r/index_merge_innodb.result'
--- a/mysql-test/r/index_merge_innodb.result	2010-12-02 13:11:15 +0000
+++ b/mysql-test/r/index_merge_innodb.result	2011-10-27 08:40:40 +0000
@@ -273,3 +273,21 @@ id	select_type	table	type	possible_keys	
 1	PRIMARY	t1	const	PRIMARY	PRIMARY	4	const	1	Using index
 2	DEPENDENT SUBQUERY	t2	index_merge	f2,f3	f3,f2	2,5	NULL	1	Using intersect(f3,f2); Using where; Using index
 DROP TABLE t1,t2;
+#
+# Bug#11747423 32254: INDEX MERGE USED UNNECESSARILY
+#
+CREATE TABLE t1 (
+id INT NOT NULL PRIMARY KEY,
+id2 INT NOT NULL,
+id3 INT NOT NULL,
+KEY (id2),
+KEY (id3),
+KEY covering_index (id2,id3)
+) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (0, 0, 0), (1, 1, 1), (2, 2, 2), (3, 3, 3), (4, 4, 4), (5, 5, 5), (6, 6, 6), (7, 7, 7);
+INSERT INTO t1 SELECT id + 8, id2 + 8, id3 +8 FROM t1;
+INSERT INTO t1 SELECT id + 16, 7, 0 FROM t1;
+EXPLAIN SELECT SQL_NO_CACHE count(*) FROM t1 WHERE id2=7 AND id3=0;
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t1	ref	id2,id3,covering_index	covering_index	8	const,const	16	Using index
+DROP TABLE t1;

=== modified file 'mysql-test/t/index_merge_innodb.test'
--- a/mysql-test/t/index_merge_innodb.test	2009-10-07 15:37:36 +0000
+++ b/mysql-test/t/index_merge_innodb.test	2011-10-27 08:40:40 +0000
@@ -28,3 +28,24 @@ let $merge_table_support= 0;
 
 --source include/index_merge_2sweeps.inc
 --source include/index_merge_ror_cpk.inc
+
+
+--echo #
+--echo # Bug#11747423 32254: INDEX MERGE USED UNNECESSARILY
+--echo #
+CREATE TABLE t1 (
+  id INT NOT NULL PRIMARY KEY,
+  id2 INT NOT NULL,
+  id3 INT NOT NULL,
+  KEY (id2),
+  KEY (id3),
+  KEY covering_index (id2,id3)
+) ENGINE=InnoDB;
+
+INSERT INTO t1 VALUES (0, 0, 0), (1, 1, 1), (2, 2, 2), (3, 3, 3), (4, 4, 4), (5, 5, 5), (6, 6, 6), (7, 7, 7);
+INSERT INTO t1 SELECT id + 8, id2 + 8, id3 +8 FROM t1;
+INSERT INTO t1 SELECT id + 16, 7, 0 FROM t1;
+
+EXPLAIN SELECT SQL_NO_CACHE count(*) FROM t1 WHERE id2=7 AND id3=0;
+
+DROP TABLE t1;

=== modified file 'sql/sql_select.cc'
--- a/sql/sql_select.cc	2011-10-27 08:08:46 +0000
+++ b/sql/sql_select.cc	2011-10-27 08:40:40 +0000
@@ -8018,7 +8018,10 @@ best_access_path(JOIN      *join,
     Don't do a table scan on InnoDB tables, if we can read the used
     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.
+    anything by using a table scan. The only exception is INDEX_MERGE
+    quick select. We can not say for sure that INDEX_MERGE quick select
+    is always faster than ref access. So it's necessary to check if
+    ref access is more expensive.
 
     A word for word translation of the below if-statement in sergefp's
     understanding: we check if we should use table scan if:
@@ -8058,8 +8061,11 @@ best_access_path(JOIN      *join,
     goto skip_table_scan;
   }
 
-  if (((s->table->file->ha_table_flags() & HA_TABLE_SCAN_ON_INDEX) &&    //(3)
-       !s->table->covering_keys.is_clear_all() && best_key && !s->quick))//(3)
+  if ((s->table->file->ha_table_flags() & HA_TABLE_SCAN_ON_INDEX) &&    //(3)
+      !s->table->covering_keys.is_clear_all() && best_key &&            //(3)
+      (!s->quick ||                                                     //(3)
+       !(s->quick->get_type() == QUICK_SELECT_I::QS_TYPE_INDEX_MERGE && //(3)
+         best > s->quick->read_time)))                                  //(3)
   {
     trace_access_scan.add_alnum("access_type", s->quick ? "range" : "scan").
       add_alnum("cause", "covering_index_better_than_full_scan");

No bundle (reason: useless for push emails).
Thread
bzr push into mysql-trunk branch (sergey.glukhov:3533 to 3534) Bug#11747423Sergey Glukhov28 Oct