MySQL 兩大主流引擎 InnoDB、MyISAM 僅支援 B-Tree 索引,**不支援 Hash 索引**。但執行 CREATE INDEX ... USING HASH 時**不會報錯**,SHOW CREATE TABLE 甚至顯示 USING HASH,實際仍建立為 B-Tree。本文實測揭露此陷阱,並介紹 InnoDB 自適應雜湊索引作為替代方案。
CREATE TABLE data_dict ( data_type VARCHAR(32) NOT NULL COMMENT '資料字典類型', data_code TINYINT(4) NOT NULL COMMENT '資料字典代碼', data_name VARCHAR(64) NOT NULL COMMENT '資料字典值', PRIMARY KEY (data_type, data_code) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='資料字典表';
ALTER TABLE data_dict ADD INDEX data_dict_dn USING HASH (data_name);
執行成功,SHOW CREATE TABLE 顯示:
KEY `data_dict_dn` (`data_name`) USING HASH
乍看似乎成功。
SHOW INDEXES FROM data_dict;
結果 Index_type 欄位顯示 BTREE,而非 HASH。MySQL 默默轉換,未給任何警告。
| 引擎 | 交易 | 鎖粒度 | B-Tree | Hash | Full-text |
|---|---|---|---|---|---|
| InnoDB | ✓ | Row | ✓ | ✗ | ✓ (5.6+) |
| MyISAM | ✗ | Table | ✓ | ✗ | ✓ |
| Memory | ✗ | Table | ✓ | ✓ | ✗ |
| NDB Cluster | ✓ | Row | ✗ | ✓ | ✗ |
| Archive | ✗ | Table | ✗ | ✗ | ✗ |
唯有 Memory 與 NDB 原生支援 Hash 索引。
InnoDB 內建 Adaptive Hash Index (AHI):監控索引查找模式,若發現建立雜湊索引能提速,自動在緩衝池中建立記憶體雜湊索引(B-Tree 頁面 → 雜湊桶)。
SHOW ENGINE INNODB STATUS;
輸出片段:
------------------------------------- INSERT BUFFER AND ADAPTIVE HASH INDEX ------------------------------------- Ibuf: size 1, free list len 2633, seg size 2635 Hash table size 348731, node heap has 2 buffer(s) 0.00 hash searches/s, 0.00 non-hash searches/s
可觀察 Hash table size、hash searches/s 判斷 AHI 效益。
SHOW ENGINES;
確認 Support 欄位為 DEFAULT、YES、NO,InnoDB 通常為預設引擎。
SHOW INDEXES 驗證 Index_type。innodb_adaptive_hash_index=ON(預設開啟)並監控 AHI 命中率。