Commit 79542930 authored by unknown's avatar unknown
Browse files

WL#3527: Extend IGNORE INDEX so places where index is ignored

         can be specified
Currently MySQL allows one to specify what indexes to ignore during
join optimization. The scope of the current USE/FORCE/IGNORE INDEX 
statement is only the FROM clause, while all other clauses are not 
affected.

However, in certain cases, the optimizer
may incorrectly choose an index for sorting and/or grouping, and
produce an inefficient query plan.

This task provides the means to specify what indexes are
ignored/used for what operation in a more fine-grained manner, thus
making it possible to manually force a better plan. We do this
by extending the current IGNORE/USE/FORCE INDEX syntax to:

IGNORE/USE/FORCE INDEX [FOR {JOIN | ORDER | GROUP BY}]

so that:
- if no FOR is specified, the index hint will apply everywhere.
- if MySQL is started with the compatibility option --old_mode then
  an index hint without a FOR clause works as in 5.0 (i.e, the 
  index will only be ignored for JOINs, but can still be used to
  compute ORDER BY).

See the WL#3527 for further details.


BitKeeper/deleted/.del-mysqld.cc.rej:
  Rename: sql/mysqld.cc.rej -> BitKeeper/deleted/.del-mysqld.cc.rej
BitKeeper/deleted/.del-sql_parse.cc.rej:
  Rename: sql/sql_parse.cc.rej -> BitKeeper/deleted/.del-sql_parse.cc.rej
BitKeeper/deleted/.del-table.cc.rej:
  Rename: sql/table.cc.rej -> BitKeeper/deleted/.del-table.cc.rej
mysql-test/r/endspace.result:
  WL3527 : fixed undeterministic test
mysql-test/r/group_by.result:
  WL#3527: test cases
mysql-test/t/endspace.test:
  WL3527 : fixed undeterministic test
mysql-test/t/group_by.test:
  WL#3527: test cases
sql/item.cc:
  WL#3527: renames
sql/mysql_priv.h:
  WL#3527: corrected initialization
sql/mysqld.cc:
  WL#3527: added old_mode command line option
sql/opt_range.cc:
  WL#3527: renames
sql/sql_base.cc:
  WL#3527: 
   - renames
   - correct initialization
   - extended the processing of USE/FORCE/IGNORE index
sql/sql_class.h:
  WL#3527: added old_mode command line option
sql/sql_delete.cc:
  WL#3527: renames
sql/sql_help.cc:
  WL#3527: renames
sql/sql_lex.cc:
  WL#3527: extended parsing of USE/FORCE/IGNORE index
sql/sql_lex.h:
  WL#3527: extended parsing of USE/FORCE/IGNORE index
sql/sql_parse.cc:
  WL#3527: extended parsing of USE/FORCE/IGNORE index
sql/sql_select.cc:
  WL#3527:
   - renames
   - passing additional info to support the extended 
     USE/FORCE/IGNORE INDEX syntax
   - If there is a covering index, and we have 
     IGNORE INDEX FOR GROUP/ORDER, and this index is 
     used for the JOIN part, then we have to ignore the
     IGNORE INDEX FOR GROUP/ORDER.
sql/sql_show.cc:
  WL#3527: passing additional info to support the extended 
     USE/FORCE/IGNORE INDEX syntax
sql/sql_update.cc:
  WL#3527: renames
sql/sql_yacc.yy:
  WL#3527: extended parsing of USE/FORCE/IGNORE index
sql/table.cc:
  WL#3527: extended the processing of USE/FORCE/IGNORE index
sql/table.h:
  WL#3527: extended the processing of USE/FORCE/IGNORE index
storage/myisam/ha_myisam.cc:
  WL#3527: extended the processing of USE/FORCE/IGNORE index
parent 92791f80
Loading
Loading
Loading
Loading
+9 −6
Original line number Diff line number Diff line
@@ -25,7 +25,8 @@ insert into t1 values ('teststring'), ('nothing'), ('teststring\t');
check table t1;
Table	Op	Msg_type	Msg_text
test.t1	check	status	OK
select * from t1 ignore key (key1) where text1='teststring' or text1 like 'teststring_%';
select * from t1 ignore key (key1) where text1='teststring' or 
text1 like 'teststring_%' ORDER BY text1;
text1
teststring	
teststring
@@ -48,7 +49,8 @@ alter table t1 modify text1 char(32) binary not null;
check table t1;
Table	Op	Msg_type	Msg_text
test.t1	check	status	OK
select * from t1 ignore key (key1) where text1='teststring' or text1 like 'teststring_%';
select * from t1 ignore key (key1) where text1='teststring' or 
text1 like 'teststring_%' ORDER BY text1;
text1
teststring	
teststring
@@ -132,7 +134,8 @@ concat('|', text1, '|')
drop table t1;
create table t1 (text1 varchar(32) not NULL, KEY key1 using BTREE (text1)) engine=heap;
insert into t1 values ('teststring'), ('nothing'), ('teststring\t');
select * from t1 ignore key (key1) where text1='teststring' or text1 like 'teststring_%';
select * from t1 ignore key (key1) where text1='teststring' or 
text1 like 'teststring_%' ORDER BY text1;
text1
teststring	
teststring
+105 −7
Original line number Diff line number Diff line
@@ -933,12 +933,110 @@ b sum(1)
18	6
19	6
DROP TABLE t1;
CREATE TABLE t1 (a INT, b INT, KEY(a));
INSERT INTO t1 VALUES (1, 1), (2, 2), (3,3), (4,4);
EXPLAIN SELECT a, SUM(b) FROM t1 GROUP BY a LIMIT 2;
CREATE TABLE t1 (a INT, b INT,
PRIMARY KEY (a),
KEY i2(a,b));
INSERT INTO t1 VALUES (1,1),(2,2),(3,3),(4,4),(5,5),(6,6),(7,7),(8,8);
INSERT INTO t1 SELECT a + 8,b FROM t1;
INSERT INTO t1 SELECT a + 16,b FROM t1;
INSERT INTO t1 SELECT a + 32,b FROM t1;
INSERT INTO t1 SELECT a + 64,b FROM t1;
INSERT INTO t1 SELECT a + 128,b FROM t1;
ANALYZE TABLE t1;
Table	Op	Msg_type	Msg_text
test.t1	analyze	status	OK
EXPLAIN SELECT a FROM t1 WHERE a < 2;
id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
1	SIMPLE	t1	index	NULL	a	5	NULL	4	
EXPLAIN SELECT a, SUM(b) FROM t1 IGNORE INDEX (a) GROUP BY a LIMIT 2;
1	SIMPLE	t1	range	PRIMARY,i2	PRIMARY	4	NULL	2	Using where; Using index
EXPLAIN SELECT a FROM t1 WHERE a < 2 ORDER BY a;
id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
1	SIMPLE	t1	ALL	NULL	NULL	NULL	NULL	4	Using temporary; Using filesort
DROP TABLE t1;
1	SIMPLE	t1	range	PRIMARY,i2	PRIMARY	4	NULL	2	Using where; Using index
EXPLAIN SELECT a FROM t1 WHERE a < 2 GROUP BY a;
id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
1	SIMPLE	t1	range	PRIMARY,i2	PRIMARY	4	NULL	2	Using where; Using index
EXPLAIN SELECT a FROM t1 IGNORE INDEX (PRIMARY,i2);
id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
1	SIMPLE	t1	ALL	NULL	NULL	NULL	NULL	256	
EXPLAIN SELECT a FROM t1 IGNORE INDEX FOR JOIN (PRIMARY,i2);
id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
1	SIMPLE	t1	ALL	NULL	NULL	NULL	NULL	256	
EXPLAIN SELECT a FROM t1 IGNORE INDEX FOR GROUP BY (PRIMARY,i2) GROUP BY a;
id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
1	SIMPLE	t1	index	NULL	PRIMARY	4	NULL	256	Using index
EXPLAIN SELECT a FROM t1 IGNORE INDEX FOR ORDER BY (PRIMARY,i2) ORDER BY a;
id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
1	SIMPLE	t1	index	NULL	PRIMARY	4	NULL	256	Using index
EXPLAIN SELECT a FROM t1 IGNORE INDEX FOR ORDER BY (PRIMARY)
IGNORE INDEX FOR GROUP BY (i2) GROUP BY a;
id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
1	SIMPLE	t1	index	NULL	PRIMARY	4	NULL	256	Using index
EXPLAIN SELECT a FROM t1 IGNORE INDEX (PRIMARY) IGNORE INDEX FOR ORDER BY (i2);
id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
1	SIMPLE	t1	index	NULL	i2	9	NULL	256	Using index
EXPLAIN SELECT a FROM t1 FORCE INDEX (i2);
id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
1	SIMPLE	t1	index	NULL	i2	9	NULL	256	Using index
EXPLAIN SELECT a FROM t1 USE INDEX ();
id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
1	SIMPLE	t1	ALL	NULL	NULL	NULL	NULL	256	
EXPLAIN SELECT a FROM t1 USE INDEX () USE INDEX (i2);
id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
1	SIMPLE	t1	ALL	NULL	NULL	NULL	NULL	256	
EXPLAIN SELECT a FROM t1 
FORCE INDEX (PRIMARY) 
IGNORE INDEX FOR GROUP BY (i2)
IGNORE INDEX FOR ORDER BY (i2)
USE INDEX (i2);
ERROR HY000: Incorrect usage of USE INDEX and FORCE INDEX
EXPLAIN SELECT a FROM t1 USE INDEX (i2) USE INDEX ();
id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
1	SIMPLE	t1	index	NULL	i2	9	NULL	256	Using index
EXPLAIN SELECT a FROM t1 FORCE INDEX ();
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ')' at line 1
EXPLAIN SELECT a FROM t1 IGNORE INDEX ();
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ')' at line 1
EXPLAIN SELECT a FROM t1 USE INDEX FOR JOIN (i2) 
USE INDEX FOR GROUP BY (i2) GROUP BY a;
id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
1	SIMPLE	t1	index	NULL	i2	9	NULL	256	Using index
EXPLAIN SELECT a FROM t1 FORCE INDEX FOR JOIN (i2) 
FORCE INDEX FOR GROUP BY (i2) GROUP BY a;
id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
1	SIMPLE	t1	range	NULL	i2	4	NULL	257	Using index for group-by
EXPLAIN SELECT a FROM t1 USE INDEX () IGNORE INDEX (i2);
id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
1	SIMPLE	t1	ALL	NULL	NULL	NULL	NULL	256	
EXPLAIN SELECT a FROM t1 IGNORE INDEX (i2) USE INDEX ();
id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
1	SIMPLE	t1	ALL	NULL	NULL	NULL	NULL	256	
EXPLAIN SELECT a FROM t1 
USE INDEX FOR GROUP BY (i2) 
USE INDEX FOR ORDER BY (i2)
USE INDEX FOR JOIN (i2);
id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
1	SIMPLE	t1	index	NULL	i2	9	NULL	256	Using index
EXPLAIN SELECT a FROM t1 
USE INDEX FOR JOIN (i2) 
USE INDEX FOR JOIN (i2) 
USE INDEX FOR JOIN (i2,i2);
id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
1	SIMPLE	t1	index	NULL	i2	9	NULL	256	Using index
EXPLAIN SELECT 1 FROM t1 WHERE a IN
(SELECT a FROM t1 USE INDEX (i2) IGNORE INDEX (i2));
id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
1	PRIMARY	t1	index	NULL	PRIMARY	4	NULL	256	Using where; Using index
2	DEPENDENT SUBQUERY	t1	ALL	NULL	NULL	NULL	NULL	256	Using where
CREATE TABLE t2 (a INT, b INT, KEY(a));
INSERT INTO t2 VALUES (1, 1), (2, 2), (3,3), (4,4);
EXPLAIN SELECT a, SUM(b) FROM t2 GROUP BY a LIMIT 2;
id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
1	SIMPLE	t2	index	NULL	a	5	NULL	4	
EXPLAIN SELECT a, SUM(b) FROM t2 IGNORE INDEX (a) GROUP BY a LIMIT 2;
id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
1	SIMPLE	t2	ALL	NULL	NULL	NULL	NULL	4	Using temporary; Using filesort
EXPLAIN SELECT 1 FROM t2 WHERE a IN
(SELECT a FROM t1 USE INDEX (i2) IGNORE INDEX (i2));
id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
1	PRIMARY	t2	index	NULL	a	5	NULL	4	Using where; Using index
2	DEPENDENT SUBQUERY	t1	ALL	NULL	NULL	NULL	NULL	256	Using where
DROP TABLE t1, t2;
+6 −3
Original line number Diff line number Diff line
@@ -16,7 +16,8 @@ drop table if exists t1;
create table t1 (text1 varchar(32) not NULL, KEY key1 (text1));
insert into t1 values ('teststring'), ('nothing'), ('teststring\t');
check table t1;
select * from t1 ignore key (key1) where text1='teststring' or text1 like 'teststring_%';
select * from t1 ignore key (key1) where text1='teststring' or 
  text1 like 'teststring_%' ORDER BY text1;
select * from t1 where text1='teststring' or text1 like 'teststring_%';
select * from t1 where text1='teststring' or text1 > 'teststring\t';
select * from t1 order by text1;
@@ -24,7 +25,8 @@ explain select * from t1 order by text1;

alter table t1 modify text1 char(32) binary not null;
check table t1;
select * from t1 ignore key (key1) where text1='teststring' or text1 like 'teststring_%';
select * from t1 ignore key (key1) where text1='teststring' or 
  text1 like 'teststring_%' ORDER BY text1;
select concat('|', text1, '|') from t1 where text1='teststring' or text1 like 'teststring_%';
select concat('|', text1, '|') from t1 where text1='teststring' or text1 > 'teststring\t';
select text1, length(text1) from t1 order by text1;
@@ -57,7 +59,8 @@ drop table t1;

create table t1 (text1 varchar(32) not NULL, KEY key1 using BTREE (text1)) engine=heap;
insert into t1 values ('teststring'), ('nothing'), ('teststring\t');
select * from t1 ignore key (key1) where text1='teststring' or text1 like 'teststring_%';
select * from t1 ignore key (key1) where text1='teststring' or 
  text1 like 'teststring_%' ORDER BY text1;
select * from t1 where text1='teststring' or text1 like 'teststring_%';
select * from t1 where text1='teststring' or text1 >= 'teststring\t';
select * from t1 order by text1;
+62 −6
Original line number Diff line number Diff line
@@ -706,10 +706,66 @@ DROP TABLE t1;
# Bug #21174: Index degrades sort performance and 
#             optimizer does not honor IGNORE INDEX
#
CREATE TABLE t1 (a INT, b INT, KEY(a));
INSERT INTO t1 VALUES (1, 1), (2, 2), (3,3), (4,4);
CREATE TABLE t1 (a INT, b INT,
                 PRIMARY KEY (a),
                 KEY i2(a,b));
INSERT INTO t1 VALUES (1,1),(2,2),(3,3),(4,4),(5,5),(6,6),(7,7),(8,8);
INSERT INTO t1 SELECT a + 8,b FROM t1;
INSERT INTO t1 SELECT a + 16,b FROM t1;
INSERT INTO t1 SELECT a + 32,b FROM t1;
INSERT INTO t1 SELECT a + 64,b FROM t1;
INSERT INTO t1 SELECT a + 128,b FROM t1;
ANALYZE TABLE t1;
EXPLAIN SELECT a FROM t1 WHERE a < 2;
EXPLAIN SELECT a FROM t1 WHERE a < 2 ORDER BY a;
EXPLAIN SELECT a FROM t1 WHERE a < 2 GROUP BY a;
EXPLAIN SELECT a FROM t1 IGNORE INDEX (PRIMARY,i2);
EXPLAIN SELECT a FROM t1 IGNORE INDEX FOR JOIN (PRIMARY,i2);
EXPLAIN SELECT a FROM t1 IGNORE INDEX FOR GROUP BY (PRIMARY,i2) GROUP BY a;
EXPLAIN SELECT a FROM t1 IGNORE INDEX FOR ORDER BY (PRIMARY,i2) ORDER BY a;
EXPLAIN SELECT a FROM t1 IGNORE INDEX FOR ORDER BY (PRIMARY)
  IGNORE INDEX FOR GROUP BY (i2) GROUP BY a;
EXPLAIN SELECT a FROM t1 IGNORE INDEX (PRIMARY) IGNORE INDEX FOR ORDER BY (i2);
EXPLAIN SELECT a FROM t1 FORCE INDEX (i2);
EXPLAIN SELECT a FROM t1 USE INDEX ();
EXPLAIN SELECT a FROM t1 USE INDEX () USE INDEX (i2);
--error ER_WRONG_USAGE
EXPLAIN SELECT a FROM t1 
  FORCE INDEX (PRIMARY) 
  IGNORE INDEX FOR GROUP BY (i2)
  IGNORE INDEX FOR ORDER BY (i2)
  USE INDEX (i2);
EXPLAIN SELECT a FROM t1 USE INDEX (i2) USE INDEX ();
--error ER_PARSE_ERROR
EXPLAIN SELECT a FROM t1 FORCE INDEX ();
--error ER_PARSE_ERROR
EXPLAIN SELECT a FROM t1 IGNORE INDEX ();
EXPLAIN SELECT a FROM t1 USE INDEX FOR JOIN (i2) 
  USE INDEX FOR GROUP BY (i2) GROUP BY a;
EXPLAIN SELECT a FROM t1 FORCE INDEX FOR JOIN (i2) 
  FORCE INDEX FOR GROUP BY (i2) GROUP BY a;
EXPLAIN SELECT a FROM t1 USE INDEX () IGNORE INDEX (i2);
EXPLAIN SELECT a FROM t1 IGNORE INDEX (i2) USE INDEX ();

EXPLAIN SELECT a FROM t1 
  USE INDEX FOR GROUP BY (i2) 
  USE INDEX FOR ORDER BY (i2)
  USE INDEX FOR JOIN (i2);

EXPLAIN SELECT a FROM t1 
  USE INDEX FOR JOIN (i2) 
  USE INDEX FOR JOIN (i2) 
  USE INDEX FOR JOIN (i2,i2);

EXPLAIN SELECT 1 FROM t1 WHERE a IN
  (SELECT a FROM t1 USE INDEX (i2) IGNORE INDEX (i2));

CREATE TABLE t2 (a INT, b INT, KEY(a));
INSERT INTO t2 VALUES (1, 1), (2, 2), (3,3), (4,4);
EXPLAIN SELECT a, SUM(b) FROM t2 GROUP BY a LIMIT 2; 
EXPLAIN SELECT a, SUM(b) FROM t2 IGNORE INDEX (a) GROUP BY a LIMIT 2;

EXPLAIN SELECT 1 FROM t2 WHERE a IN
  (SELECT a FROM t1 USE INDEX (i2) IGNORE INDEX (i2));

EXPLAIN SELECT a, SUM(b) FROM t1 GROUP BY a LIMIT 2; 
EXPLAIN SELECT a, SUM(b) FROM t1 IGNORE INDEX (a) GROUP BY a LIMIT 2;

DROP TABLE t1;
DROP TABLE t1, t2;
+1 −1
Original line number Diff line number Diff line
@@ -3828,7 +3828,7 @@ bool Item_field::fix_fields(THD *thd, Item **reference)
      {
        /* First usage of column */
        table->used_fields++;                     // Used to optimize loops
        table->used_keys.intersect(field->part_of_key);
        table->covering_keys.intersect(field->part_of_key);
      }
    }
  }
Loading