### 8.9.4 索引提示

[](<>)[](<>)[](<>)[](<>)[](<>)[](<>)[](<>)[](<>)

索引提示为优化器提供有关如何在查询处理期间选择索引的信息。此处描述的索引提示与在中描述的优化器提示不同[第 8.9.3 节，“优化器提示”](optimizer-hints.html).索引和优化器提示可以单独使用，也可以一起使用。

索引提示仅适用于[`选择`](select.html)和[`更新`](update.html)陈述。

索引提示在表名之后指定。（对于在 a 中指定表的一般语法[`选择`](select.html)声明，见[第 13.2.10.2 节，“JOIN 子句”](join.html).) 引用单个表的语法（包括索引提示）如下所示：

```
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] ...
```

这`使用索引 (*`索引列表`*)`提示告诉 MySQL 仅使用一个命名索引来查找表中的行。替代语法`忽略索引 (*`索引列表`*)`告诉 MySQL 不要使用某些特定的索引或索引。这些提示很有用，如果[`解释`](explain.html)表明 MySQL 使用了可能索引列表中的错误索引。

这`力指数`提示就像`使用索引 (*`索引列表`*)`，此外假定表扫描是*非常*昂贵的。换句话说，只有在无法使用命名索引之一来查找表中的行时才使用表扫描。

笔记

从 MySQL 8.0.20 开始，服务器支持索引级优化器提示[`JOIN_INDEX`](optimizer-hints.html#optimizer-hints-index-level),[`GROUP_INDEX`](optimizer-hints.html#optimizer-hints-index-level),[`ORDER_INDEX`](optimizer-hints.html#optimizer-hints-index-level)， 和[`指数`](optimizer-hints.html#optimizer-hints-index-level), 等同于并旨在取代`力指数`索引提示，以及[`NO_JOIN_INDEX`](optimizer-hints.html#optimizer-hints-index-level),[`NO_GROUP_INDEX`](optimizer-hints.html#optimizer-hints-index-level),[`NO_ORDER_INDEX`](optimizer-hints.html#optimizer-hints-index-level)， 和[`NO_INDEX`](optimizer-hints.html#optimizer-hints-index-level)优化器提示，等同于并旨在取代`忽略索引`索引提示。因此，您应该期望`使用索引`,`力指数`， 和`忽略索引`在 MySQL 的未来版本中被弃用，并在此后的某个时间被完全删除。有关详细信息，请参阅[索引级优化器提示](optimizer-hints.html#optimizer-hints-index-level).

每个提示都需要索引名称，而不是列名称。要引用主键，请使用名称`基本的`.要查看表的索引名称，请使用[`显示索引`](show-index.html)声明或[`INFORMATION_SCHEMA.STATISTICS`](information-schema-statistics-table.html)桌子。

一个*`索引名称`*value 不必是完整的索引名称。它可以是索引名称的明确前缀。如果前缀不明确，则会发生错误。

例子：

```
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;
```

索引提示的语法具有以下特征：

-   省略在语法上是有效的*`索引列表`*对于`使用索引`，意思是“不使用索引”省略*`索引列表`*对于`力指数`或`忽略索引`是一个语法错误。

-   可以通过添加`对于`从句的意思。这为查询处理的各个阶段的执行计划的优化器选择提供了更细粒度的控制。要仅影响MySQL决定如何查找表中的行以及如何处理联接时使用的索引，请使用`加入`.要影响排序或分组行的索引使用，请使用`订购`或`分组讨论`.

-   您可以指定多个索引提示：

    ```
    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);
    ```

    然而，混用是错误的`使用索引`和`力指数`对于同一张表：

    ```
    SELECT * FROM t1 USE INDEX FOR JOIN (i1) FORCE INDEX FOR JOIN (i2);
    ```

    如果索引提示中没有`对于`子句中，提示的范围适用于语句的所有部分。例如，以下提示：


```
IGNORE INDEX (i1)
```

相当于以下提示的组合：

```
IGNORE INDEX FOR JOIN (i1)
IGNORE INDEX FOR ORDER BY (i1)
IGNORE INDEX FOR GROUP BY (i1)
```

在MySQL 5.0中，提示作用域没有`对于`子句仅适用于行检索。使服务器在没有`对于`子句存在时，启用[`古老的`](server-system-variables.html#sysvar_old)服务器启动时的系统变量。请注意在复制设置中启用此变量。对于基于语句的二进制日志记录，源和副本的模式不同可能会导致复制错误。

在处理索引提示时，它们会按类型收集到单个列表中(`使用`, `武力`, `忽视`)从范围来看(`加入`, `订购`, `分组讨论`).例如：

```
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}索引`如果存在，则应用。（如果不是，则使用优化器确定的索引集。）

2.  `忽略索引`应用于上一步的结果。例如，以下两个查询是等效的：

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

    SELECT * FROM t1 USE INDEX (i1);
    ```

    对于`全文`搜索、索引提示的工作方式如下：

-   对于自然语言模式搜索，索引提示会被忽略。例如`忽略索引（i1）`在没有警告的情况下被忽略，并且索引仍在使用。

-   对于布尔模式搜索，使用`订购`或`分组讨论`他们默默地被忽略了。索引提示`加入`或者不`对于`我很荣幸。与提示如何适用于非-`全文`搜索时，提示用于查询执行的所有阶段（查找行和检索、分组和排序）。这是真的，即使提示是针对非-`全文`指数

    例如，以下两个查询是等效的：

    ```
    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 ... ;
    ```
