MySQL?EXPLAIN中的key_len索引使用實(shí)戰(zhàn)解析
深入解析MySQL執(zhí)行計(jì)劃中最關(guān)鍵的指標(biāo)之一,助你快速定位索引優(yōu)化點(diǎn),提升查詢性能!
一、key_len:索引使用的精準(zhǔn)標(biāo)尺
在MySQL執(zhí)行計(jì)劃中,key_len表示查詢實(shí)際使用索引的字節(jié)長度。這個指標(biāo)是索引優(yōu)化的核心,它能揭示:
- 復(fù)合索引使用深度:顯示使用了復(fù)合索引的前幾列
- 索引利用效率:值越大,索引利用率越高
- 索引失效檢測:NULL值表示索引未被使用
- 數(shù)據(jù)類型成本:不同數(shù)據(jù)類型在索引中的開銷
二、key_len計(jì)算的核心規(guī)則(重點(diǎn)掌握?。?/h2>
1. 基礎(chǔ)計(jì)算規(guī)則
key_len = 數(shù)據(jù)類型基礎(chǔ)長度 + NULL標(biāo)記(1字節(jié)) + 變長類型額外開銷(2字節(jié))
2. 常用數(shù)據(jù)類型計(jì)算表(utf8mb4環(huán)境)
| 數(shù)據(jù)類型 | 基礎(chǔ)長度 | NULL開銷 | VARCHAR開銷 | NOT NULL示例 | NULL示例 |
|---|---|---|---|---|---|
| INT | 4字節(jié) | +1字節(jié) | - | 4 | 5 |
| BIGINT | 8字節(jié) | +1字節(jié) | - | 8 | 9 |
| TINYINT | 1字節(jié) | +1字節(jié) | - | 1 | 2 |
| FLOAT | 4字節(jié) | +1字節(jié) | - | 4 | 5 |
| DOUBLE | 8字節(jié) | +1字節(jié) | - | 8 | 9 |
| DATE | 3字節(jié) | +1字節(jié) | - | 3 | 4 |
| DATETIME | 8字節(jié) | +1字節(jié) | - | 8 | 9 |
| TIMESTAMP | 4字節(jié) | +1字節(jié) | - | 4 | 5 |
| CHAR(10) | 10×字符集字節(jié) | +1字節(jié) | - | 40 (utf8mb4) | 41 (utf8mb4) |
| VARCHAR(50) | 50×字符集字節(jié) | +1字節(jié) | +2字節(jié) | 202 (utf8mb4) | 203 (utf8mb4) |
核心要點(diǎn):
VARCHAR類型在索引中固定增加2字節(jié)長度前綴(實(shí)際行存儲時規(guī)則不一致:≤255字符+1字節(jié),>255字符+2字節(jié))
字符集直接影響長度:utf8mb4=4字節(jié)/字符,latin1=1字節(jié)/字符
NULL列增加1字節(jié)開銷
三、key_len實(shí)戰(zhàn)解析:從案例學(xué)優(yōu)化
案例1:復(fù)合索引使用深度判斷
-- 表結(jié)構(gòu) CREATE TABLE users ( id INT PRIMARY KEY, name VARCHAR(50) NOT NULL, -- key_len:50×4+2=202 age TINYINT NOT NULL, -- key_len:1 email VARCHAR(100) NOT NULL, -- key_len:100×4+2=402 INDEX idx_profile (name, age, email) ) CHARSET=utf8mb4; -- 場景1:僅使用name列 EXPLAIN SELECT * FROM users WHERE name = 'John'; -- key_len = 202(復(fù)合索引第一列) -- 場景2:使用前兩列 EXPLAIN SELECT * FROM users WHERE name = 'John' AND age = 30; -- key_len = 203(202+1) -- 場景3:使用所有列 EXPLAIN SELECT * FROM users WHERE name = 'John' AND age = 30 AND email = 'john@example.com'; -- key_len = 605(202+1+402)
案例2:字符集對key_len的影響
-- latin1字符集對比 CREATE TABLE logs_latin1 ( message VARCHAR(100) NOT NULL ) CHARSET=latin1; CREATE TABLE logs_utf8mb4 ( message VARCHAR(100) NOT NULL ) CHARSET=utf8mb4; EXPLAIN SELECT * FROM logs_latin1 WHERE message = 'error'; -- key_len = 102 (100×1 + 2) EXPLAIN SELECT * FROM logs_utf8mb4 WHERE message = 'error'; -- key_len = 402 (100×4 + 2)
案例3:NULL值的隱藏成本
-- 允許NULL的列 ALTER TABLE users MODIFY age TINYINT NULL; -- 相同查詢條件 EXPLAIN SELECT * FROM users WHERE name = 'John' AND age = 30; -- key_len = 204(202+1+1,比非NULL多1字節(jié))
四、key_len揭示的三大優(yōu)化機(jī)會
1. 復(fù)合索引優(yōu)化(核心!)
當(dāng)key_len < 索引總長度時:
- 問題:索引未充分利用
- 解決方案:
-- 1. 補(bǔ)充缺失查詢條件 SELECT ... WHERE col1=1 AND col2=2 AND col3=3 -- 2. 重建索引(高頻查詢列前置) ALTER TABLE orders DROP INDEX idx_old; ALTER TABLE orders ADD INDEX idx_new (status, user_id, created_at); -- 3. 使用覆蓋索引 SELECT indexed_columns FROM table WHERE ...
2. VARCHAR列優(yōu)化策略
-- 方案1:前綴索引(減少長度) ALTER TABLE products ADD INDEX (description(20)); -- key_len從402降為82(VARCHAR(100)→20×4+2)
3. 消除NULL存儲開銷
-- 優(yōu)化前(允許NULL) ALTER TABLE users MODIFY phone VARCHAR(20) NULL; -- key_len=20×4+2+1=83 -- 優(yōu)化后(禁止NULL) ALTER TABLE users MODIFY phone VARCHAR(20) NOT NULL DEFAULT ''; -- key_len=82(節(jié)省1字節(jié)/行)
五、高級診斷技巧
1. EXPLAIN FORMAT=JSON(推薦)
EXPLAIN FORMAT=JSON
SELECT * FROM users WHERE name='Lisa';
/* 輸出片段 */
{
"query_block": {
"table": {
"key_length": 202,
"used_key_parts": ["name"],
// ...其他信息
}
}
}
2. 性能優(yōu)化檢查清單
- 檢查key_len是否接近索引長度
- 確認(rèn)復(fù)合索引是否滿足最左前綴原則
- 分析VARCHAR列長度是否合理
- 檢查是否有不必要的NULL列
- 對比不同字符集下的索引大小
六、總結(jié):key_len優(yōu)化四原則
- 追求最大key_len:值越接近索引總長度,索引利用越充分
- 警惕NULL開銷:每允許一個NULL列,key_len增加1字節(jié)
- VARCHAR成本控制:長文本字段優(yōu)先考慮前綴索引或哈希
- 最左前綴原則:確保查詢條件從復(fù)合索引最左側(cè)開始
終極技巧:當(dāng)發(fā)現(xiàn)key_len顯著小于索引長度時,立即檢查:
- 是否缺少必要查詢條件?
- 索引列順序是否合理?
- 是否存在數(shù)據(jù)類型轉(zhuǎn)換?
- 字符集選擇是否合適?
到此這篇關(guān)于MySQL EXPLAIN中的key_len索引使用實(shí)戰(zhàn)解析的文章就介紹到這了,更多相關(guān)mysql explain key_len使用內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
mysql索引過長Specialed key was too long的解決方法
在創(chuàng)建要給表的時候遇到一個有意思的問題,提示Specified key was too long; max key length is 767 bytes,本文就來介紹一下解決方法,如果你也遇到此類問題,可以參考一下2021-11-11
MySQL插入、更新與刪除表中數(shù)據(jù)實(shí)現(xiàn)方式
本文介紹了MySQL數(shù)據(jù)插入、更新和刪除的操作方法,包括直接添加、沒有字段名添加、部分字段添加、多行添加等插入方法,UPDATE語句更新記錄,DELETE語句刪除記錄,以及TRUNCATE語句刪除表中所有記錄,最后總結(jié)了TRUNCATE與DELETE的區(qū)別2026-04-04
MySQL入門(二) 數(shù)據(jù)庫數(shù)據(jù)類型詳解
這個數(shù)據(jù)庫所遇到的數(shù)據(jù)類型今天統(tǒng)統(tǒng)在這里講清楚了,以后在看到什么數(shù)據(jù)類型,咱度應(yīng)該認(rèn)識,對我來說,最不熟悉的應(yīng)該就是時間類型這塊了。但是通過今天的學(xué)習(xí),已經(jīng)解惑了。下面就跟著我的節(jié)奏去把這個拿下吧2018-07-07
MySql下關(guān)于時間范圍的between查詢方式
這篇文章主要介紹了MySql下關(guān)于時間范圍的between查詢方式,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-07-07
MySQL存儲表情時報(bào)錯:java.sql.SQLException: Incorrect string value:‘
這篇文章主要給大家介紹了關(guān)于MySQL存儲表情時報(bào)錯:java.sql.SQLException: Incorrect string value: '\xF0\x9F\x92\xA9\x0D\x0A...'的解決方法,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考借鑒,下面來一起看看吧。2018-04-04

