8.9.4 索引提示

索引提示为优化器提供有关在查询处理期间如何选择索引的信息。此处描述的索引提示与第 8.9.3 节“优化程序提示”中描述的优化器提示不同。索引和优化器提示可以单独使用,也可以一起使用。

索引提示仅适用于SELECTUPDATE语句。

在 table 名后指定索引提示。 (有关在SELECT语句中指定 table 的常规语法,请参见第 13.2.9.2 节“ JOIN 子句”。)引用单个 table(包括索引提示)的语法如下所示:

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 (index_list)提示告诉 MySQL 仅使用命名索引之一来查找 table 中的行。替代语法IGNORE INDEX (index_list)告诉 MySQL 不要使用某些特定的索引。如果EXPLAIN显示 MySQL 使用的索引可能不正确,则这些提示很有用。

FORCE INDEX提示的作用类似于USE INDEX (index_list),另外,还假定 table 扫描非常昂贵。换句话说,仅当无法使用命名索引之一在 table 中查找行时才使用 table 扫描。

每个提示都需要索引名称,而不是列名称。要引用主键,请使用名称PRIMARY。要查看 table 的索引名称,请使用SHOW INDEX语句或INFORMATION_SCHEMA.STATISTICStable。

  • index_name *值不必是完整的索引名称。它可以是索引名称的明确前缀。如果前缀不明确,则会发生错误。

Examples:

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;

索引提示的语法具有以下 Feature:

  • 在语法上,对USE INDEX省略* index_list 是合法的,这意味着“不使用索引”。 FORCE INDEXIGNORE INDEX省略 index_list *是语法错误。

  • 您可以通过在提示中添加FOR子句来指定索引提示的范围。这为查询处理的各个阶段提供了对执行计划的优化器选择的更精细控制。要只影响 MySQL 决定如何在 table 中查找行以及如何处理联接时使用的索引,请使用FOR JOIN。要影响索引对行进行排序或分组的用法,请使用FOR ORDER BYFOR 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 INDEXFORCE INDEX混合用于同一张 table 是错误的:

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)

在 MySQL 5.0 中,没有FOR子句的提示作用域仅适用于行检索。若要在不存在FOR子句的情况下使服务器使用此较旧的行为,请在服务器启动时启用old系统变量。请注意在复制设置中启用此变量。使用基于语句的二进制日志记录,对源和副本使用不同的模式可能会导致复制错误。

处理索引提示后,它们将按类型(USEFORCEIGNORE)和作用域(FOR JOINFOR ORDER BYFOR GROUP BY)收集在一个列 table 中。例如:

SELECT * FROM t1
  USE INDEX () IGNORE INDEX (i2) USE INDEX (i1) USE INDEX (i2);

等效于:

SELECT * FROM t1
   USE INDEX (i1,i2) IGNORE INDEX (i2);

然后按以下 Sequences 将索引提示应用于每个范围:

  • {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 BYFOR GROUP BY的索引提示将被忽略。带有FOR JOIN或没有FOR修饰符的索引提示会受到重视。与提示适用于非FULLTEXT搜索的方式相反,提示用于查询执行的所有阶段(查找行和检索,分组和排序)。即使为非FULLTEXT索引提供了提示,也是如此。

例如,以下两个查询是等效的:

SELECT * FROM t
  USE INDEX (index1)
  IGNORE INDEX (index1) FOR ORDER BY
  IGNORE INDEX (index1) FOR GROUP BY
  WHERE ... IN BOOLEAN MODE ... ;

SELECT * FROM t
  USE INDEX (index1)
  WHERE ... IN BOOLEAN MODE ... ;