使用explain
分析sql性能时,里面有一列key_len
。
该列显示了MySQL使用的索引的字节数
。对于多列组成的联合索引
,如果MySQL只是使用了联合索引
里的某些列,通过key_value
的值可以算出是哪些列。
但是key_value
的值是怎样计算得到的?上图中字段mobile
的类型是char(11)
,key_value
的值是33
。
查阅了资料,总结下部分计算规则。
- int - 4个字节,bigint - 8个字节
- char, varchar - 需要根据使用字符集来判断,GBK使用2个字节编码一个字符,UTF8使用3个字节编码一个字符
- 对于varchar,需要额外的2个字节来保存长度信息。
- 可以是null的字段,需要额外的一个字节来保存NULL。
下面是一些具体的例子
CREATE TABLE `shu_users` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '用户id',
`name` char(11) NOT NULL DEFAULT '' COMMENT '用户名',
`mobile` char(11) NOT NULL DEFAULT '' COMMENT '手机号码',
`create_time` int(11) DEFAULT 0 COMMENT '创建时间',
PRIMARY KEY (`id`),
UNIQUE KEY `mobile` (`mobile`),
KEY `create_time` (`create_time`),
KEY `name_create_time` (`name`, `create_time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='用户表'
- 主键id是int类型,而且not null,所以
key_len=4
。
explain select * from shu_users where id = 2;
- 字段create_time是int类型,同时允许值为null,
key_len=4+1=5
。
explain select * from shu_users where create_time = 1401262736;
- 字段mobile是char(11)类型,不允许值为null, 表的字符集是
utf8
,key_len=11*3=33
。
explain select * from shu_users where mobile = "13333333333";
- 如果将mobile字段修改为varchar(11)类型,且允许值为null,表的字符集还是
utf8
,key_len=11*3+2+1=36
。
explain select * from shu_users where mobile = "13333333333";
- 对应联合索引
name_create_time
, 下面的sql只用到索引的第一列name
,name字段的类型是varchar(11)类型,不允许值为null,key_value=11*3+2=35
。
explain select * from shu_users where name like "李%";