兩類非常隱蔽的全表掃描,不能命中索引

原文鏈接:https://mp.weixin.qq.com/s?__biz=MjM5ODYxMDA5OQ==&mid=2651962477&idx=1&sn=3a7617781a095243953fed8f236abab3&chksm=bd2d09b18a5a80a756784da67c636e518ca006c16a0ff4e7165de5fa01b82454403dc7c6d83b&scene=21#wechat_redirect

兩類非常隱蔽的全表掃描,不能命中索引

第一類:“列類型”與“where值類型”不符,不能命中索引,會導致全表掃描(full table scan)。

數據準備:

create table t1 (
cell varchar(3) primary key
)engine=innodb default charset=utf8;

insert into t1(cell) values ('111'),('222'),('333');

(1)cell屬性爲varchar類型;

(2)cell爲主鍵,即聚簇索引(clustered index);

(3)t1插入3條測試數據;

測試語句:

explain select * from t1 where cell=111;
explain select * from t1 where cell='111';

(1)第一個語句,where後的值類型是整數(與表cell類型不符);

(2)第二個語句,where後的值類型是字符串(與表cell類型一致);

測試結果:
在這裏插入圖片描述
(1)強制類型轉換,不能命中索引,需要全表掃描,即3條記錄;

(2)類型相同,命中索引,1條記錄;

第二類:相join的兩個表的字符編碼不同,不能命中索引,會導致笛卡爾積的循環計算(nested loop)。

數據準備:

create table t2 (
cell varchar(3) primary key
)engine=innodb default charset=latin1;

insert into t2(cell) values ('111'),('222'),('333'),('444'),('555'),('666');

create table t3 (
cell varchar(3) primary key
)engine=innodb default charset=utf8;

insert into t3(cell) values ('111'),('222'),('333'),('444'),('555'),('666');

(1)t2和t1字符集不同,插入6條測試數據;

(2)t3和t1字符集相同,也插入6條測試數據;

(3)除此之外,t1,t2,t3表結構完全相同;

測試語句:

explain select * from t1,t2 where t1.cell=t2.cell;
explain select * from t1,t3 where t1.cell=t3.cell;

(1)第一個join,連表t1和t2(字符集不同),關聯屬性是cell;

(2)第一個join,連表t1和t3(字符集相同),關聯屬性是cell;

測試結果:
在這裏插入圖片描述
(1)t1和t2字符集不同,存儲空間不同;

(2)t1和t2相join時,遍歷了t1的所有記錄3條,t1的每一條記錄又要遍歷t2的所有記錄6條,實際進行了笛卡爾積循環計算(nested loop),索引無效;

(3)t1和t3相join時,遍歷了t1的所有記錄3條,t1的每一條記錄使用t3索引,即掃描1行記錄;

總結

兩類隱蔽的不能利用索引的case:
(1)表列類型,與where值類型,不一致;

(2)join表的字符編碼不同;

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章