Documentation Home
MySQL 8.4 Reference Manual
Related Documentation Download this Manual
PDF (US Ltr) - 39.8Mb
PDF (A4) - 39.9Mb
Man Pages (TGZ) - 257.9Kb
Man Pages (Zip) - 364.9Kb
Info (Gzip) - 4.0Mb
Info (Zip) - 4.0Mb


10.9.4 索引提示

索引提示提供了优化器关于选择索引的信息,以便在查询处理中进行选择。这里描述的索引提示不同于optimizer hints,见第10.9.3节,“Optimizer Hints”。索引和优化器提示可以单独使用或同时使用。

索引提示适用于SELECTUPDATE语句。它们也可以与多表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 (index_list)提示告诉 MySQL 使用指定的索引来查找表中的行。alternative 语法为IGNORE INDEX (index_list),告诉 MySQL 不要使用某些特定的索引或索引。这些提示在EXPLAIN显示 MySQL 使用了错误的索引时非常有用。

FORCE INDEX提示符类似于USE INDEX (index_list)

Note

MySQL 8.4 支持索引级优化器提示JOIN_INDEXGROUP_INDEXORDER_INDEXINDEX,这些提示等同于并且旨在取代FORCE INDEX索引提示,以及NO_JOIN_INDEXNO_GROUP_INDEXNO_ORDER_INDEXNO_INDEX优化器提示,等同于并且旨在取代IGNORE INDEX索引提示。因此,您应该预期USE INDEXFORCE INDEXIGNORE 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_listUSE INDEX是合法的,这意味着“使用无 indexes.”省略index_listFORCE INDEXIGNORE INDEX是一个语法错误。

  • 您可以通过添加一个FOR子句来指定索引提示的作用域。这提供了更细粒度的控制,以便优化器选择执行计划的各种阶段。要影响MySQL在表中找到行和处理连接时使用的索引,请使用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

    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)

当处理索引提示时,它们将根据类型(USEFORCEIGNORE)和作用域(FOR JOINFOR ORDER BYFOR 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);

然后,对每个作用域,索引提示将按以下顺序应用:

  1. {USE|FORCE} INDEX如果存在,则应用。如果不存在,则使用优化器确定的索引集。

  2. 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搜索中索引提示的应用方式不同,这里提示用于查询执行的所有阶段(找到行和检索、分组和排序)。这 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)