一道关于索引的使用和key_len的计算的面试题

题目如下:

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).

百思不得骑姐啊.

就查资料,找到了下面这篇文章

MySQL key_len 大小的计算

看到了下面这段话

变长字段需要额外的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的长度是以字节为单位的.

你可能感兴趣的:(mysql)