一、key_len:索引使用的精准标尺
在mysql执行计划中,key_len表示查询实际使用索引的字节长度。这个指标是索引优化的核心,它能揭示:
- 复合索引使用深度:显示使用了复合索引的前几列
- 索引利用效率:值越大,索引利用率越高
- 索引失效检测:null值表示索引未被使用
- 数据类型成本:不同数据类型在索引中的开销
explain select * from orders where user_id = 100 and status = 'shipped'; -- 输出示例(修正对齐问题): +----+-------------+--------+------+---------------+---------+---------+-------------+------+-------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | extra | +----+-------------+--------+------+---------------+---------+---------+-------------+------+-------+ | 1 | simple | orders | ref | idx_composite | idx_composite | 86 | const,const | 1 | null | +----+-------------+--------+------+---------------+---------+---------+-------------+------+-------+
二、key_len计算的核心规则(重点掌握!)
1. 基础计算规则
key_len = 数据类型基础长度 + null标记(1字节) + 变长类型额外开销
2. 常用数据类型计算表(utf8mb4环境)
数据类型 | 基础长度 | null开销 | varchar开销 | not null示例 | null示例 |
---|---|---|---|---|---|
int | 4字节 | +1字节 | - | 4 | 5 |
bigint | 8字节 | +1字节 | - | 8 | 9 |
tinyint | 1字节 | +1字节 | - | 1 | 2 |
float | 4字节 | +1字节 | - | 4 | 5 |
double | 8字节 | +1字节 | - | 8 | 9 |
date | 3字节 | +1字节 | - | 3 | 4 |
datetime | 8字节 | +1字节 | - | 8 | 9 |
timestamp | 4字节 | +1字节 | - | 4 | 5 |
char(10) | 10×字符集字节 | +1字节 | - | 40 (utf8mb4) | 41 (utf8mb4) |
varchar(50) | 50×字符集字节 | +1字节 | +2字节 | 202 (utf8mb4) | 203 (utf8mb4) |
decimal(10,2) | 整数4字节+小数2字节 | +1字节 | - | 6 | 7 |
核心要点:
- varchar类型在索引中固定增加2字节长度前缀(实际行存储:≤255字符+1字节,>255字符+2字节)
- 字符集直接影响长度:utf8mb4=4字节/字符,latin1=1字节/字符
- null列增加1字节开销
三、key_len实战解析:从案例学优化
案例1:复合索引使用深度判断
-- 表结构 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(复合索引第一列) -- 场景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字节)
四、key_len揭示的三大优化机会
1. 复合索引优化(核心!)
当key_len < 索引总长度时:
问题:索引未充分利用
解决方案:
-- 1. 补充缺失查询条件 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列优化策略
-- 方案1:前缀索引(减少长度) alter table products add index (description(20)); -- key_len从402降为82(varchar(100)→20×4+2) -- 方案2:enum替代(有限值场景) alter table orders modify status enum('pending','shipped','completed') not null; -- key_len≈1-2字节 -- 方案3:压缩长文本+哈希索引 alter table articles add column content_hash binary(16) not null, add index (content_hash);
3. 消除null存储开销
-- 优化前(允许null) alter table users modify phone varchar(20) null; -- key_len=20×4+2+1=83 -- 优化后(禁止null) alter table users modify phone varchar(20) not null default ''; -- key_len=82(节省1字节/行)
五、高级诊断技巧
1. explain format=json(推荐)
explain format=json select * from users where name='lisa'; /* 输出片段 */ { "query_block": { "table": { "key_length": 202, "used_key_parts": ["name"], // ...其他信息 } } }
2. 性能优化检查清单
- 检查key_len是否接近索引长度
- 确认复合索引是否满足最左前缀原则
- 分析varchar列长度是否合理
- 检查是否有不必要的null列
- 对比不同字符集下的索引大小
六、总结:key_len优化四原则
- 追求最大key_len:值越接近索引总长度,索引利用越充分
- 警惕null开销:每允许一个null列,key_len增加1字节
- varchar成本控制:长文本字段优先考虑前缀索引或哈希
- 最左前缀原则:确保查询条件从复合索引最左侧开始
终极技巧:当发现key_len显著小于索引长度时,立即检查:
- 是否缺少必要查询条件?
- 索引列顺序是否合理?
- 是否存在数据类型转换?
- 字符集选择是否合适?
通过精准解读key_len,您将获得索引优化的"x光视力"。下次查看explain结果时,重点关注key_len值——这个不起眼的数字可能是性能突破的关键!
到此这篇关于mysql explain中key_len使用的终极指南的文章就介绍到这了,更多相关mysql explain使用内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论