MySQL 中的索引


索引用來加速查詢。正常來說,當查詢數據時,MySQL 需要從表的第一條記錄開始,讀取整個表的內容,進行查詢。

但如果有索引,MySQL 可根據索引快速定位需要查詢條目的具體位置,加快了查詢速度。

原理

索引的原理是將被索引列的值,單獨取出來存到另一種結構中以獲取快速查詢的效果。

當列有這些屬性中任意一個時,會被索引, PRIMARY KEYUNIQUEINDEX, 以及 FULLTEXT

大部分索引以 B-trees 結構存儲。但有些例外:

  • Spatial Data 數據類型,一種基於地理坐標使用數字來標識現實中對象的數據類型,使用 R-trees
  • MEMORY 內存表同時支持使用 hash 索引
  • InnoDB 引擎中對於全文本索引(FULLTEXT)直接使用列表(lists)結構。

MySQL 使用索引的場景

以下場景將借助或依賴於索引:

  • 使用 WHERE 進行條件查詢時
  • 用於排除一些記錄。存在多個索引可選時,MySQL 選擇會獲取最小記錄的那個索引(the most selective index)。
  • 存在多列索引的情況下,從左排開始的列的組合都可用於查詢時的優化。比如三個索引列 (col1, col2, col3),查詢時可以有這些組合的優化查詢 (col1), (col1, col2), and (col1, col2, col3),詳見 Section 8.3.6, “Multiple-Column Indexes”
  • 聯表查詢時。特別地,如果列的類型及大小相同的話,查詢時會更加高效。比如 VARCHAR 和 CHAR 會當成同一類型,VARCHAR(10) and CHAR(15) 則不是同一類型,因為長度不同。
  • 使用 MIN()MAX() 函數時。
  • 進行排序或分組時。
  • 某些情況下,僅僅通過索引就能完成查詢操作,無須操作真實的表記錄。這種提供了查詢中足夠信息的索引被稱為 covering index

索引並不是萬能的,對於數據量小的表以及對於那些查詢全部數據的操作,索引的效果並不明顯。相反,對於那些查詢時涉及到表中大部分數據的情況下,逐條查詢比使用索引要快。

索引的類型

主要有以下四種索引類型,關於創建索引的其他詳情可參見 MySQL Manual - 13.1.15 CREATE INDEX Syntax

  • Index Prefixes
  • FULLTEXT 索引
  • Spatial 索引
  • MEMORY Storage Engine 中的索引

Index Prefixes

對於字符串類型的列,在索引創建語法中指定 col_name(N),可將該列中前 N 個字符進行索引。通過只索引列中前 N 個字符 而非整列,可有效減小索引大小。比如索引 BLOB or TEXT 類型的列:

CREATE TABLE test (blob_col BLOB, INDEX(blob_col(10)));

查詢時,如果查詢項超過了索引長度,索引將用來排除掉那些在索引長度范圍內匹配失敗的記錄,剩下的記錄則正常查詢。

FULLTEXT 索引

全文本索引用於全文本(full-text)的搜索。只 InnoDBMyISAM 兩種引擎下的 CHAR,VARCHAR,TEXT 數據類型支持全文本索引。不像 Index Prefixes,該類型的索引是會對整列的。

Spatial 索引

Spatial Data 數據類型 上創建的索引。

MEMORY Storage Engine 中的索引

 MEMORY 存儲引擎默認使用 HASH 索引,但也支持 BTREE 索引。

索引的創建

索引可在創建表時創建,參考 13.1.20 CREATE TABLE Syntax,也可針對已有的表進行創建,使用 CREATE INDEX 語句。

創建索引的語法
CREATE [UNIQUE | FULLTEXT | SPATIAL] INDEX index_name
    [index_type]
    ON tbl_name (key_part,...)
    [index_option]
    [algorithm_option | lock_option] ...

key_part: {col_name [(length)] | (expr)} [ASC | DESC]

index_option:
KEY_BLOCK_SIZE [=] value
| index_type
| WITH PARSER parser_name
| COMMENT 'string'
| {VISIBLE | INVISIBLE}

index_type:
USING {BTREE | HASH}

algorithm_option:
ALGORITHM [=] {DEFAULT | INPLACE | COPY}

lock_option:
LOCK [=] {DEFAULT | NONE | SHARED | EXCLUSIVE}

有如下類型的索引指定方式,

  • 以列前綴的方/Column Prefix Key Parts
  • 函數形式/Functional Key Parts
  • Unique 索引
  • Full-Text 索引
  • Spatial 索引

以列前綴的方

可用於創建列中指定前綴部分 col_name(length) 的索引。

示例:

CREATE INDEX part_of_name ON customer (name(10));

以上語句對名為 name 的例索引其前 10 個字符。

函數形式

普通形式的索引只能索引列中的值,比如:

CREATE TABLE t1 (
  col1 VARCHAR(10),
  col2 VARCHAR(20),
  INDEX (col1, col2(10))
);

以上語句對 col1 整列 及 col2 前 10 個字符進行索引。

但使用函數形式,可創建針對表達式的索引,而不是表中的列。

CREATE TABLE t1 (col1 INT, col2 INT, INDEX func_index ((ABS(col1))));
CREATE INDEX idx1 ON t1 ((col1 + col2));
CREATE INDEX idx2 ON t1 ((col1 + col2), (col1 - col2), col1);
ALTER TABLE t1 ADD INDEX ((col1 * 40) DESC);

函數形式的索引在定義時需要滿足以下的條件,否則拋錯:

  • 表達式使用括號包裹,以和列名或列的其他前綴屬性區別開來。
/* 🚨 */
INDEX (col1 + col2, col3 - col4)

//
INDEX ((col1 + col2), (col3 - col4))

  • 函數形式的表達式不能形成一個單獨的列名,譬如:
/* 🚨 */
INDEX ((col1), (col2))

//
INDEX (col1, col2)

  • 函數中不能引用列前綴(column prefixes)。
  • 外鍵(foreign key)中不使用使用函數形式。

Unique 索引

指定為 UNIQUE 的列約束了列中的值在記錄中是唯一的,嘗試插入重復值時會拋錯。但允許存在多個 NULL 值,如果該列允許為空的話。

如果一個表擁有 PRIMARY KEYUNIQUE NOT NULL 類型的單列整型形成的索引,在 SELECT 語句中可使用 _rowid 關鍵詞來獲取索引的列:

  • 如果存在一個整型的 PRIMARY KEY 列,_rowid 則指代該列。
  • 否則 _rowid 指代第一個 UNIQUE NOT NULL 列。如果不存在一個 UNIQUE NOT NULL 類型的整型列,則不能使用 _rowid

Full-Text 索引

詳細的操作參見 12.9.7 Adding a Collation for Full-Text Indexing

Spatial 索引

不同存儲引擎對其支持情況不一,詳見 Spatial Indexes

相關資源


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM