索引用於快速尋找具有特定欄位值的列。若沒有索引,MySQL 必須從第一列開始,然後讀取整個資料表才能找到相關的列。資料表越大,成本就越高。如果資料表有所需欄位的索引,MySQL 可以快速判斷在資料檔中間要搜尋的位置,而無需查看所有資料。這比依序讀取每一列快得多。
大多數 MySQL 索引 (PRIMARY KEY、UNIQUE、INDEX 和 FULLTEXT) 都儲存在 B 樹中。例外情況:空間資料類型上的索引使用 R 樹;MEMORY 資料表也支援 雜湊索引;InnoDB 使用倒置列表作為 FULLTEXT 索引。
一般來說,索引的使用方式如下所述。雜湊索引的特定特性 (在 MEMORY 資料表中使用) 在第 10.3.9 節「B 樹和雜湊索引的比較」中有說明。
MySQL 使用索引進行下列操作
快速尋找符合
WHERE子句的列。排除考慮的列。如果有多個索引可供選擇,MySQL 通常會使用尋找最少列的索引 (最具選擇性的索引)。
如果資料表具有多欄索引,最佳化工具可以使用索引的任何最左側前綴來尋找列。例如,如果您在
(col1, col2, col3)上建立三欄索引,您可以在(col1)、(col1, col2)和(col1, col2, col3)上建立索引搜尋功能。如需更多資訊,請參閱第 10.3.6 節「多欄索引」。在執行聯結時,從其他資料表擷取列。如果 MySQL 欄位的宣告類型和大小相同,則可以更有效率地使用欄位上的索引。在這種情況下,如果宣告的大小相同,
VARCHAR和CHAR會被視為相同。例如,VARCHAR(10)和CHAR(10)的大小相同,但VARCHAR(10)和CHAR(15)的大小不同。對於非二進位字串欄位之間的比較,這兩個欄位應該使用相同的字元集。例如,比較
utf8mb4欄位和latin1欄位會排除使用索引。比較不同類型的資料欄(例如,將字串欄位與時間或數值欄位進行比較)可能會因為數值無法在未經轉換的情況下直接比較,而導致無法使用索引。例如,數值欄位中的值
1可能會與字串欄位中的許多值相等,例如'1'、' 1'、'00001'或'01.e1'。這會排除對字串欄位使用任何索引的可能性。尋找特定索引欄位
key_col的MIN()或MAX()值。這會由預處理器最佳化,該預處理器會檢查您是否在索引中key_col之前的所有索引鍵部分使用了WHERE。在這種情況下,MySQL 會為每個key_part_N=constantMIN()或MAX()運算式執行單一索引鍵查找,並將其替換為常數。如果所有運算式都被替換為常數,則查詢會立即返回。例如SELECT MIN(key_part2),MAX(key_part2) FROM tbl_name WHERE key_part1=10;如果排序或分組是依據可用索引的最左側前綴來完成,則對表格進行排序或分組(例如,
ORDER BY)。如果所有索引鍵部分都後接key_part1,key_part2DESC,則會以反向順序讀取索引鍵。(或者,如果索引是降序索引,則會以正向順序讀取索引鍵。)請參閱 第 10.2.1.16 節,「ORDER BY 最佳化」、第 10.2.1.17 節,「GROUP BY 最佳化」 和 第 10.3.13 節,「降序索引」。在某些情況下,可以最佳化查詢以檢索值,而無需查詢資料列。(提供查詢所需所有結果的索引稱為涵蓋索引。)如果查詢僅使用表格中包含在某些索引中的欄位,則可以從索引樹中檢索選定的值以提高速度。
SELECT key_part3 FROM tbl_name WHERE key_part1=1
對於小型表格或報表查詢處理大多數或所有列的大型表格,索引的重要性較低。當查詢需要存取大多數列時,循序讀取比透過索引工作更快。循序讀取可最大程度地減少磁碟搜尋,即使查詢並非需要所有列。請參閱 第 10.2.1.23 節,「避免完整表格掃描」以取得詳細資訊。