10.9.4 索引提示
索引提示提供了优化器关于选择索引的信息,以便在查询处理中进行选择。这里描述的索引提示不同于optimizer hints,见第10.9.3节,“Optimizer Hints”。索引和优化器提示可以单独使用或同时使用。
索引提示适用于SELECT、UPDATE语句。它们也可以与多表DELETE语句一起使用,但不能与单表DELETE语句一起使用,如后续部分所示。
索引提示在表名前指定。 (关于在SELECT语句中指定表的通用语法,见第15.2.13.2节,“JOIN Clause”。) 指定单个表、包括索引提示的语法如下:
tbl_name [[AS] alias] [index_hint_list]
index_hint_list:
index_hint [index_hint] ...
index_hint:
USE {INDEX|KEY}
[FOR {JOIN|ORDER BY|GROUP BY}] ([index_list])
| {IGNORE|FORCE} {INDEX|KEY}
[FOR {JOIN|ORDER BY|GROUP BY}] (index_list)
index_list:
index_name [, index_name] ...
USE INDEX (提示告诉 MySQL 使用指定的索引来查找表中的行。alternative 语法为index_list)IGNORE INDEX (,告诉 MySQL 不要使用某些特定的索引或索引。这些提示在index_list)EXPLAIN显示 MySQL 使用了错误的索引时非常有用。
FORCE INDEX提示符类似于USE INDEX (index_list)
MySQL 8.4 支持索引级优化器提示JOIN_INDEX、GROUP_INDEX、ORDER_INDEX和INDEX,这些提示等同于并且旨在取代FORCE INDEX索引提示,以及NO_JOIN_INDEX、NO_GROUP_INDEX、NO_ORDER_INDEX和NO_INDEX优化器提示,等同于并且旨在取代IGNORE INDEX索引提示。因此,您应该预期USE INDEX、FORCE INDEX和IGNORE INDEX将在 MySQL 的未来版本中被弃用,并且在某个时候将被完全删除。
这些索引级优化器提示支持单表和多表DELETE语句。
更多信息,请见索引级优化器提示。
每个提示都需要索引名称,而不是列名称。要引用主键,请使用名称PRIMARY。要查看表的索引名称,请使用SHOW INDEX语句或信息_schema中的STATISTICS表。
一个index_name值不需要是完整的索引名称。它可以是一个索引名称的不ambiguous前缀。如果前缀是ambiguous,会出现错误。
示例:
SELECT * FROM table1 USE INDEX (col1_index,col2_index)
WHERE col1=1 AND col2=2 AND col3=3;
SELECT * FROM table1 IGNORE INDEX (col3_index)
WHERE col1=1 AND col2=2 AND col3=3;
索引提示语法具有以下特点:
-
省略
index_list对USE INDEX是合法的,这意味着“使用无 indexes.”省略index_list对FORCE INDEX或IGNORE INDEX是一个语法错误。 -
您可以通过添加一个
FOR子句来指定索引提示的作用域。这提供了更细粒度的控制,以便优化器选择执行计划的各种阶段。要影响MySQL在表中找到行和处理连接时使用的索引,请使用FOR JOIN。要影响索引使用的排序或分组行,请使用FOR ORDER BY或FOR GROUP BY。 -
您可以指定多个索引提示:
SELECT * FROM t1 USE INDEX (i1) IGNORE INDEX FOR ORDER BY (i2) ORDER BY a;可以在多个提示中使用同名的索引名称(即使是在同一个提示中):
SELECT * FROM t1 USE INDEX (i1) USE INDEX (i1,i1);然而,对于同一张表,不能混合使用
USE INDEX和FORCE INDEX:SELECT * FROM t1 USE INDEX FOR JOIN (i1) FORCE INDEX FOR JOIN (i2);
如果索引提示不包含FOR子句,那么该提示的作用域是对整个语句的应用。例如,这个提示:
IGNORE INDEX (i1)
等同于这个组合提示:
IGNORE INDEX FOR JOIN (i1)
IGNORE INDEX FOR ORDER BY (i1)
IGNORE INDEX FOR GROUP BY (i1)
当处理索引提示时,它们将根据类型(USE、FORCE、IGNORE)和作用域(FOR JOIN、FOR ORDER BY、FOR GROUP BY)收集在一个列表中。例如:
SELECT * FROM t1
USE INDEX () IGNORE INDEX (i2) USE INDEX (i1) USE INDEX (i2);
等同于:
SELECT * FROM t1
USE INDEX (i1,i2) IGNORE INDEX (i2);
然后,对每个作用域,索引提示将按以下顺序应用:
-
{USE|FORCE} INDEX如果存在,则应用。如果不存在,则使用优化器确定的索引集。 -
IGNORE INDEX在前一步骤的结果上应用。例如,以下两个查询等同:SELECT * FROM t1 USE INDEX (i1) IGNORE INDEX (i2) USE INDEX (i2); SELECT * FROM t1 USE INDEX (i1);
对于FULLTEXT搜索,索引提示工作如下:
-
对于自然语言模式搜索,索引提示将被忽略。例如,
IGNORE INDEX(i1)将被忽略无警告,并且仍然使用该索引。 -
对于布尔模式搜索,带有
FOR ORDER BY或FOR GROUP BY的索引提示将被忽略。带有FOR JOIN或无FOR修饰符的索引提示将被尊重。在非FULLTEXT搜索中索引提示的应用方式不同,这里提示用于查询执行的所有阶段(找到行和检索、分组和排序)。这 même 如果提示给定于一个非FULLTEXT索引。例如,以下两个查询是等效的:
SELECT * FROM t USE INDEX (index1) IGNORE INDEX FOR ORDER BY (index1) IGNORE INDEX FOR GROUP BY (index1) WHERE ... IN BOOLEAN MODE ... ; SELECT * FROM t USE INDEX (index1) WHERE ... IN BOOLEAN MODE ... ;
索引提示与DELETE语句一起工作,但只能在使用多表DELETE语法时,如下所示:
mysql> EXPLAIN DELETE FROM t1 USE INDEX(col2)
-> WHERE col1 BETWEEN 1 AND 100 AND COL2 BETWEEN 1 AND 100\G
ERROR 1064 (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 'use
index(col2) where col1 between 1 and 100 and col2 between 1 and 100' at line 1
mysql> EXPLAIN DELETE t1.* FROM t1 USE INDEX(col2)
-> WHERE col1 BETWEEN 1 AND 100 AND COL2 BETWEEN 1 AND 100\G
*************************** 1. row ***************************
id: 1
select_type: DELETE
table: t1
partitions: NULL
type: range
possible_keys: col2
key: col2
key_len: 5
ref: NULL
rows: 72
filtered: 11.11
Extra: Using where
1 row in set, 1 warning (0.00 sec)