MySQL 哈希索引、空間數(shù)據(jù)索引、全文索引
緊接上一小節(jié),本小節(jié)重點(diǎn)介紹哈希索引、空間數(shù)據(jù)索引、全文索引。
1.哈希索引
哈希索引基于哈希表實現(xiàn),僅支持精確匹配索引所有列的查詢。對于每行數(shù)據(jù),存儲引擎都會對所有的索引列計算出一個哈希碼。哈希索引將所有的哈希碼存儲在索引中,同時保存指向每個數(shù)據(jù)行的指針。
1.1 存儲結(jié)構(gòu)
常見的存儲引擎中,MEMORY 存儲引擎顯式支持哈希索引。如果多個列的哈希值相同,哈希索引會以鏈表的方式存放多個記錄指針到同一個哈希條目中。
以 customer 表為例,我們來看看索引是如何組織數(shù)據(jù)的存儲的:
mysql> create table customer(
id int,
last_name varchar(30),
first_name varchar(30),
birth_date date,
key idx1_customer(first_name) using hash
) ENGINE=MEMORY;
mysql> select * from customer;
+------+-----------+------------+------------+
| id | last_name | first_name | birth_date |
+------+-----------+------------+------------+
| 1 | Allen | Cuba | 1960-01-01 |
| 2 | Barrymore | Julia | 2000-05-06 |
| 3 | Basinger | Viven | 1979-01-24 |
+------+-----------+------------+------------+
3 rows in set (0.00 sec)
假設(shè)哈希索引使用哈希函數(shù)f(),返回的值如下:
f('Cuba')=1212
f('Julia')=5656
f('Viven')=2323
哈希索引的數(shù)據(jù)結(jié)構(gòu)如下:
+-----------+-----------------------+
| 槽(Slot) | 值(Value) |
+-----------+-----------------------+
| 1212 | 指向第1行的指針 |
| 2323 | 指向第3行的指針 |
| 5656 | 指向第2行的指針 |
+-----------+-----------------------+
InnoDB 存儲引擎也能支持哈希索引,但它所支持的哈希索引是自適應(yīng)的。InnoDB 存儲引擎會根據(jù)表的使用情況,在內(nèi)存中基于 B-Tree 索引之上再創(chuàng)建一個哈希索引,這種行為是自動的、內(nèi)部的行為,不能人為去干預(yù)是否在一張表中生成哈希索引。
1.2 適合哈希索引的查詢類型
精確匹配所有列
和索引中的所有列進(jìn)行精確匹配,如查找名字為Julia的客戶。
數(shù)據(jù)庫先會計算first_name='Julia’的哈希值5656,然后在索引中查找5656,找到對應(yīng)的指針為:指向第2行的指針,最后根據(jù)指針從原表拿到具體值,并進(jìn)行比較是否為Julia
mysql> explain select * from customer where first_name='Julia'\G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: customer
partitions: NULL
type: ref
possible_keys: idx1_customer
key: idx1_customer
key_len: 93
ref: const
rows: 2
filtered: 100.00
Extra: NULL
1 row in set, 1 warning (0.00 sec)
1.3 哈希索引的限制
- 哈希索引只支持等值查詢,包括=、IN、<=>;
- 哈希索引不存儲字段值,只包含哈希值和行指針,不能使用索引中的值來避免讀取行;
- 哈希索引不是按照索引值順序存儲的,不能用于排序;
- 哈希索引不支持部分索引列匹配查找,如在字段(last_name,first_name)創(chuàng)建哈希索引,此時需要查找last_name='Allen’的數(shù)據(jù)行,這種查詢無法使用該哈希索引;
- 哈希索引不支持范圍查詢,如查找所有姓氏在Allen和Bush之間的客戶,這種查詢無法使用哈希索引;
- 如果出現(xiàn)很多哈希沖突(不同的索引列值有相同的哈希值),索引的維護(hù)成本是很高的,應(yīng)盡量避免在選擇性很低的字段上創(chuàng)建哈希索引。
2.空間數(shù)據(jù)索引 R-Tree
常見的存儲引擎中,MyISAM 存儲引擎支持空間索引,主要用作地理數(shù)據(jù)存儲。空間索引會從所有維度來索引數(shù)據(jù),查詢時,可以使用任意維度來組合查詢。這點(diǎn)和 B-Tree 索引不同,空間索引不需要前綴查詢。MySQL 的 GIS 支持其實并不完善,一般情況并不建議在 MySQL 中使用空間索引。
3.全文索引
全文索引查找的是文本中的關(guān)鍵詞,并不是直接比較索引中的值,它是一種特殊類型的索引。全文索引和其他索引的匹配方式完全不一樣,更類似于搜索引擎,并不是簡單的 where 條件匹配。
在相同的列上可以同時創(chuàng)建全文索引和 B-Tree 索引,全文索引適用于 match against 操作,不是簡單的where 條件操作。
4.小結(jié)
本小節(jié)介紹了哈希索引、空間數(shù)據(jù)索引、全文索引這三種索引類型。重點(diǎn)介紹了哈希索引的存儲結(jié)構(gòu)、適合哈希索引的查詢類型和相關(guān)限制。哈希索引僅支持精確匹配所有列的查詢,在這種查詢中,哈希索引是非常高效的,因為哈希索引存儲的是哈希值,存儲結(jié)構(gòu)非常緊湊。