[MYSQL] mysql执行计划中的key
导读
当我们查看执行计划的时候, 会看到一个叫做key_len
的字段, 顾名思义, 该字段是指索引的长度.
对此官方文档描述如下:
The key_len column indicates the length of the key that MySQL decided to use. The value of key_len enables you to determine how many parts of a multiple-part key MySQL actually uses. If the key column says NULL, the key_len column also says NULL.
Due to the key storage format, the key length is one greater for a column that can be NULL than for a NOT NULL column.
大意是 key_len是使用了某个索引多少字节, 如果索引可为空, 则还得+1
太晦涩了. 那我们就来研究研究这个没用的细节.
分析
官网虽然说得比较简单, 但大概意思是明白的, 主要是包含 索引字段大小, 再额外加上一些信息(比如能否非空), 对于可变长字段(比如varchar)可能还会加上额外的值(这部分是猜想的).
非复合索引
然后我们来创建一张表并查看其执行计划:
代码语言:sql复制create table t20250319_1(aa char(10), bb char(10) not null, cc varchar(10), dd varchar(10) not null, key(aa), key(bb), key(cc), key(dd)) default character set latin1;
explain select * from t20250319_1 where aa='1';
explain select * from t20250319_1 where bb='1';
explain select * from t20250319_1 where cc='1';
explain select * from t20250319_1 where dd='1';
得到其执行计划如下:
我们稍微整理下
数据类型 | 元数据大小(字节) | 可否为空 | key_len值 |
---|---|---|---|
char | 10 | 可以为空 | 11 |
char | 10 | 不可以为空 | 10 |
varchar | 10 | 可以为空 | 13 |
varchar | 10 | 可以为空 | 12 |
证明我们上述的猜想是正确的. 即: key_len = meta_size * Maxlen + 2(如果是变长类型) + 1(如果可以为空)
meta_size 指varchar(10)中的10 Maxlen是指该字符集 字符使用的最大字节数(show character set;)
我们画图表示就是:
看起来简单粗暴.
欸, 那复合索引呢?
复合索引
关于复合索引的key_len我们大概有2种可能
- 复合索引的这个key_len是每个字段计算出来的key_len相加,
- 还是 所有的key字段相加 然后再考虑+1,+2问题呢?
看起来后者更合理一点. 但对于非复合索引计算得都那么简单粗暴了, 复合索引估计还是简单粗暴的第1种计算方式.
我们来验证下:
代码语言:sql复制create table t20250319_2(
c1 varchar(1),
c2 varchar(1),
c3 varchar(1),
c4 varchar(1),
c5 varchar(1),
c6 varchar(1),
c7 varchar(1),
c8 varchar(1),
c9 varchar(1),
key(c1,c2,c3,c4,c5,c6,c7,c8,c9)
) default character set latin1;
explain select * from t20250319_2 where c1='a';
explain select * from t20250319_2 where c1='a' and c2='a';
explain select * from t20250319_2 where c1='a' and c2='a' and c3='a';
explain select * from t20250319_2 where c1='a' and c2='a' and c3='a' and c4='a' and c5='a' and c6='a' and c7='a' and c8='a' and c9='a';
我们得到执行计划如下:
还是整理一下:
使用索引字段数量 | key_len值 |
---|---|
1 | 4 |
2 | 8 |
3 | 12 |
9 | 36 |
发现确实是使用的简单粗暴的 每个字段的key_len相加. 虽然这个索引实际上可能最多才使用 9(变量长度) + 2(null bitmask) + 9(数据长度) = 20字节, 但计算出来的key_len已经为36字节了.
总结
关于mysql执行计划中的key_len计算方式则为:
单个索引字段的key_len为: 数据最大长度(字节) + 2(如果是变长字段) + 1(如果可为空),
所有 使用的索引字段 的key_len加起来就是最终的 key_len.
参考:
.0/en/explain-output.html#explain_key_len
发布者:admin,转转请注明出处:http://www.yc00.com/web/1748211992a4748581.html
评论列表(0条)