mysql中explain關鍵字可以模擬mysql優化器執行sql語句,是乙個可以很好的分析sql語句或表結構的效能瓶頸。
explain的使用方法:explain + sql語句,下面我們先來執行下explain語句
explain select * from `user` where created_time > "2020-03-08";
執行結果如下:
可以看到有幾個返回引數:id、select_type、table、partitions、type、possible_keys、key、key_len、ref、rows、filtererd、extra。
下面先介紹下這些引數的含義
id // 選擇識別符號
select_type // 表示查詢的型別
table // 輸出結果集的表
partitions // 匹配的分割槽
type // 表示表的連線型別,
possible_keys // 表示查詢時,可能使用的索引
key // 表示實際使用的索引
key_len // 索引欄位的長度
ref // 列與索引的比較
rows // 掃瞄出的行數(估算的行數)
filtered // 按表條件過濾的行百分比
extra // 執**況的描述和說明
我們把比較重要的引數提取出來進行詳細講解一下:
表示連線型別,型別有all、index、range、 ref、eq_ref、const、system、null,這幾種型別從左到右,效能越來越高。一般乙個好的sql語句至少要達到range級別。all級別應當杜絕
all:全表掃瞄,應當避免該型別
index:索引全域性掃瞄,index與all區別為index型別只遍歷索引樹
range:檢索索引一定範圍的行
ref:非唯一性索引掃瞄,返回匹配某個單獨值的所有行
eq_ref:唯一索引掃瞄,對於每個索引鍵,表中只有一條記錄與之匹配。常見主鍵或唯一索引掃瞄
const:表示通過一次索引就找到了結果,常出現於primary key或unique索引
system:system是const型別的特例,當查詢的表只有一行的情況下,使用system
null:mysql在優化過程中分解語句,執行時甚至不用訪問表或索引,是最高的登記
表示實際使用到的索引,如果為null,則沒有使用索引
表示使用索引長度
表示根據sql情況,預估表的掃瞄行數
表示詳細說明,注意該值包含十分重要的資訊。一般該列存在下列值,常見的不太友好的值有:using filesort, using temporary
using where // 表示不用讀取表中所有資訊,僅通過索引就可以獲取所需資料,即使用列覆蓋索引
using temporary // 表示需要使用臨時表來儲存結果集,常見於排序和分組查詢,如:group by ; order by
using filesort // 表示無法利用索引完成的排序
using join buffer // 表示使用了連線快取,如果出現了這個值,建議根據查詢的具體情況可能需要新增索引來改進能。
impossible where // 表示where語句會一直false,導致沒有符合條件的行(通過收集統計資訊不可能存在結果)
select tables optimized away // 這個值意味著sql優化到不能在優化了
no tables used // query語句中使用from dual 或不含任何from子句
好了,我們對explain執行計畫做了乙個基本的介紹,下面我們來看看in到底會不會走索引
建立表如下:
create table `test` (
`id` int not null auto_increment,
`name` varchar(120) default null comment '姓名',
`age` int default null,
primary key (`id`),
key `idx_name` (`name`)
) engine=innodb default charset=utf8 comment='測試表';
插入資料
insert into `test`.`test`(`id`, `name`, `age`) values (1, 'xiaoming', 18);
執行explain執行計畫
explain select * from test where name in ("lisi")
檢視結果
可以看到in確實走了所以 idx_name,那是不是in永遠都會走索引呢?
我們通過儲存過程插入10000條資料
delimiter //
drop procedure if exists inserttestdata;
create procedure inserttestdata () begin
declare i int;
set i = 0;
while i < 10000 do
insert into test(`name`, `age`) values (concat('xiaoming', concat( i, '' )), 18);
set i = i + 1;
end while;
end //
call inserttestdata();
delimiter ;
此時我們再看下是不是in繼續走索引
explain select * from test where name in ("lisi","xiaoming1")
發現依舊走索引
此時我們再插入2000條"lisi"這樣的資料
delimiter //
drop procedure if exists inserttestdata;
create procedure inserttestdata () begin
declare i int;
set i = 0;
while i < 2000 do
insert into test(`name`, `age`) values ('lisi', 18);
set i = i + 1;
end while;
end //
call inserttestdata();
delimiter ;
執行依舊in走索引,那是不是意味著in一定走索引呢?當我們再繼續執行2次插入2000條"lisi",即資料庫有6000條name=「lisi」的資料時,神奇的發現in並不走索引了,如下圖
in通常是走索引的,當in後面的資料在資料表中超過30%
(上面的例子的匹配資料大約6000/16000 = 37.5%)的匹配時,會走全表掃瞄,即不走索引,因此in走不走索引和後面的資料有關係。 附:
mysql中explain用法和結果分析(詳解)-mysql教程-php中文網
mysql 索引 大於等於 走不走索引 最左字首
你可以認為聯合索引是闖關遊戲的設計 例如你這個聯合索引是state city zipcode 那麼state就是第一關 city是第二關,zipcode就是第三關 你必須匹配了第一關,才能匹配第二關,匹配了第一關和第二關,才能匹配第三關 你不能直接到第二關的 索引的格式就是第一層是state,第二層...
mysql不走索引總結
在mysql查詢語句中,總會發現明明已經建立了查詢字段索引,可是卻沒有用到,這是因為在mysql中有些查詢語句是用不到索引的,總結如下,以供大家分享。1.like語句 2.列型別為字串型別,查詢時沒有用單引號引起來 3.在where查詢語句中使用表示式 4.在where查詢語句中對字段進行null值...
Mysql中哪些Sql不走索引
select sname from stu where age 10 30 不會使用索引,因為所有索引列參與了計算 select sname from stu where left date 4 1990 不會使用索引,因為使用了函式運算,原理與上面相同 select from houdunwang...