索引提示提供最佳化工具關於如何在查詢處理期間選擇索引的資訊。此處描述的索引提示與 第 10.9.3 節,「最佳化工具提示」中描述的最佳化工具提示不同。索引和最佳化工具提示可以單獨或一起使用。
索引提示適用於 SELECT
和 UPDATE
語句。它們也適用於多資料表 DELETE
語句,但不適用於單一資料表 DELETE
,如本節稍後所示。
索引提示在資料表名稱後指定。(關於在 SELECT
語句中指定資料表的一般語法,請參閱 第 15.2.13.2 節,「JOIN 子句」。)包含索引提示的個別資料表參考語法如下
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 僅使用指定的索引之一來尋找資料表中的資料列。替代語法 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
語句或 Information Schema STATISTICS
資料表。
index_name
值不需要是完整的索引名稱。它可以是不含歧義的索引名稱字首。如果字首有歧義,就會發生錯誤。
範例
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;
索引提示的語法具有下列特性
省略
USE INDEX
的index_list
在語法上是有效的,這表示 「不使用任何索引。」 省略FORCE INDEX
或IGNORE INDEX
的index_list
是一個語法錯誤。您可以透過在提示中加入
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
搜尋不同,該提示會被用於查詢執行的所有階段(尋找列和檢索、分組和排序)。即使該提示是針對非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)