1. 程式人生 > >MySQL 中的索引

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)的搜尋。只 InnoDB 和 MyISAM 兩種引擎下的 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);

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

  • 表示式使用括號包裹,以和列名或列的其他字首屬性區別開來。
/*