key_len 表示**查詢實際使用到的索引鍵長度 (字節)**。通過對比「理論索引鍵長度」與「實際 key_len」,可精準判斷**聯合索引有多少列參與了查找/排序/分組**。
| 數據類型 | 存儲字節 | key_len 計算 | 備註 |
|---|---|---|---|
| TINYINT | 1 | 1 (+1 if NULL) | |
| SMALLINT | 2 | 2 (+1 if NULL) | |
| MEDIUMINT | 3 | 3 (+1 if NULL) | |
| INT / INTEGER | 4 | 4 (+1 if NULL) | |
| BIGINT | 8 | 8 (+1 if NULL) | |
| CHAR(N) | N × 字符集字節數 | N × 字節數 (+1 if NULL) | utf8mb4=4, utf8=3, latin1=1 |
| VARCHAR(N) | 實際長度 + 1~2 字節長度前綴 | N × 字節數 + 2 (+1 if NULL) | 長度前綴:<255 用 1 字節,≥255 用 2 字節 |
| DATE | 3 | 3 (+1 if NULL) | |
| DATETIME / TIMESTAMP | 5.6.4 前 8 / 4;5.6.4+ 5+fsp / 4+fsp | 同上 (+1 if NULL) | fsp=微秒精度 0~6 |
| DECIMAL(M,D) | 按 9 位/4 字節分組 | 實際存儲字節 (+1 if NULL) | 見下文詳細算法 |
MySQL 索引中為每個**允許 NULL** 的列預留 1 字節標誌位 (0=非空, 1=空)。NOT NULL 列無此開銷,這也是建議「核心業務列設 NOT NULL」的原因之一。
DECIMAL(M,D):整數部 M-D 位,小數部 D 位,分別按 9 位一組打包。
CREATE TABLE t (
a INT NOT NULL PRIMARY KEY,
b INT DEFAULT NULL,
c INT DEFAULT NULL,
d INT DEFAULT NULL,
KEY ix_bcd (b, d, c) -- 聯合索引順序:b, d, c
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
ALTER TABLE t DROP INDEX ix_bcd, ADD INDEX ix_bcd (b, c, d); EXPLAIN SELECT a FROM t WHERE b = 5 AND d = 10 ORDER BY c; +----+-------------+-------+------+---------------+-------+---------+-------+------+--------------------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+-------+------+---------------+-------+---------+-------+------+--------------------------+ | 1 | SIMPLE | t | ref | ix_bcd | ix_bcd| 5 | const | 2 | Using where; Using index | +----+-------------+-------+------+---------------+-------+---------+-------+------+--------------------------+
key_len=5 = (4+1) → **僅命中第 1 列 (b)**WHERE b=5 AND d=10 中 d 是索引第 3 列,**跳過第 2 列 (c) 導致索引失效** (最左前綴原則)。rows=2 → 回表掃描 2 行,性能大幅下降。EXPLAIN 輸出的 key_len 實際值。