1. 程式人生 > >一道關於索引的使用和key_len的計算的面試題

一道關於索引的使用和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).

百思不得騎姐啊.

就查資料,找到了下面這篇文章

看到了下面這段話

變長欄位需要額外的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的長度是以位元組為單位的.