题目如下:
mysql有一个联合索引KEY(a,b,c),a为tinyint类型(长度为1),b为mediumint类型(长度为3),c为int类型(长度4)。写出条件where a=1 and c=1所使用到的此索引的长度。
我的思路是这个联合索引(复合索引),只用到了最左的a.所以长度应该是1.当然长度也可能是8(1+3+4),即任何情况下,用到了索引,key_len的长度都是这个索引的整体长度.
测试:
创建一个表
create table abc
(
id int primary key auto_increment,
a TINYINT,
b MEDIUMINT,
c int
)
插入数据
insert into abc(a,b,c) VALUES(1,1,1);
添加索引
alter table abc add key abc(a,b,c);
测试
select id from abc where a = 1 and c = 1; # 测试结果key_len = 2
执行计划居然显示key_len是2. 我一下就瞎了!!!
继续测试
select id from abc where a = 1 and b = 1; # 测试结果key_len = 6
select id from abc where a = 1 and b = 1 and c = 1; # 测试结果key_len = 11
测试结果分别是2,6,11 而我的想法是1,4,8(分别为1,1+3,1+3+4).
百思不得骑姐啊.
就查资料,找到了下面这篇文章
看到了下面这段话
变长字段需要额外的2个字节,固定长度字段不需要额外的字节。而null都需要1个字节的额外空间,所以索引字段最好不要为NULL,因为NULL让统计更加复杂,并且需要额外一个字节的存储空间。
然后参照自己的结果,得到了证实.2,6,11分别是(1+1,4+2,8+3).因为abc三个字段我都没有设置not null.
继续测试.
创建表,插入数据,添加索引
create table abcnotnull
(
id int primary key auto_increment,
a TINYINT not null,
b MEDIUMINT not NULL,
c int not NULL
)
insert into abcnotnull(a,b,c) VALUES(1,1,1);
alter table abcnotnull add key abc(a,b,c);
测试
select id from abcnotnull where a = 1 and c = 1; # 测试结果key_len = 1
select id from abcnotnull where a = 1 and b = 1; # 测试结果key_len = 4
select id from abcnotnull where a = 1 and b = 1 and c = 1; # 测试结果key_len = 8
再次证实了 null都需要1个字节的额外空间.
需要注意的是varchar(10)和char(10)指的是10个字符,他们的字节长度和具体的字符编码有关.如utf-8一个字符就是三个字符.key_len的长度是以字节为单位的.