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)