MySQL索引優化(二)索引失效

本文主要說的是索引失效問題

創建表

create table if not exists staffs(
    id int primary key auto_increment,
    name varchar(24) not null default '' comment '姓名',
    age int not null default 0 comment '年齡',
    pos varchar(20) not null default '' comment '職位',
    add_time timestamp not null default current_timestamp comment '入職時間'
)comment '員工記錄表';

insert into staffs(name, age, pos, add_time) values ('z3', 22, 'manager', NOW());
insert into staffs(name, age, pos, add_time) values ('July', 23, 'dev', NOW());
insert into staffs(name, age, pos, add_time) values ('2000', 23, 'dev', NOW());



添加索引

alter table staffs add index idx_staffs_nameAgePos(name, age, pos);

1、左前綴法則

先看一個正常的

explain select * from staffs where name = 'July' and age = 23 and pos = 'dev';

結果如下
在這裏插入圖片描述
由ref下的三個const可知,三個索引都被使用到了,key_len的長度也可以體現。說明這個是正常的sql查詢。

1)帶頭索引不能少

name字段的索引是帶頭索引,這裏不使用name字段的索引。

explain select * from staffs where age = 23 and pos = 'dev';

結果如下
在這裏插入圖片描述
可知type類型變成了最糟糕的ALL,且key_len的長度爲null,說明三個索引都沒有用到。

2)中間索引不能丟

age字段的索引爲中間索引,所以使用age字段的索引。

explain select * from staffs where name = 'July' and pos = 'dev';

結果如下
在這裏插入圖片描述
由ref下的一個const可知,索引只使用到了一個,也就是帶頭索引。

3)結論

綜上,如果可以全值匹配就全值匹配(條件字段和索引一樣),要遵守左前綴法則,查詢從索引的最左前列開始並且不跳過索引中的列。

2、 不在索引列上做任何操作

這裏的操作包括計算、函數、類型轉換,會導致索引失效而轉向全表掃描。

select * from staffs where name = 'July';
select * from staffs where left(name, 4) = 'July';

執行這兩條sql都可以得到想要的結果。
在這裏插入圖片描述
執行

explain select * from staffs where left(name, 4) = 'July';

結果如下
在這裏插入圖片描述
會發現索引失效了。

3、 少用範圍查詢

執行

explain select * from staffs where name = 'July' and age = 23;
explain select * from staffs where name = 'July' and age > 23;

結果如下
在這裏插入圖片描述
type類型由ref降低爲range。

4、減少使用select *

儘量使用覆蓋索引(只訪問索引的查詢(索引列和查詢列一致)),減少select *

explain select * from staffs where name = 'July' and age = 23;

在這裏插入圖片描述
只取想要的數據。

explain select name, age, pos from staffs where name = 'July' and age = 23;

結果如下
在這裏插入圖片描述
Extra出現了Using index,表明性能更優了。

5、不等於

使用不等於(!=或者<>)的時候無法使用索引會導致全表掃描。

explain select * from staffs where name = 'July' and age != 23;

在這裏插入圖片描述
type變爲ALL,索引失效了。

6、is null,is not null

is null,is not null也無法使用索引。

explain select * from staffs where name = 'July' and age is null;

在這裏插入圖片描述
創建字段的時候,儘量避免空值null。

6、like和通配符

like以通配符開頭(%abc)索引也會失效,變成全表掃描。
分別執行

explain select * from staffs where name = 'July';
explain select * from staffs where name like 'July';
explain select * from staffs where name like '%July';

結果如下
在這裏插入圖片描述
可以看見第三條sql的索引失效。所以like的時候,百分號加右邊。

如何解決like ‘%字符串%’ 時索引不會被使用?
使用覆蓋索引即可解決(只要查詢的字段是索引字段即可)。
在這裏插入圖片描述
可以看到type變爲了index,性能比ALL好了不少。

7、 字符串不加單引號

字符串不加單引號索引失效。

explain select * from staffs where name = 2000;

結果如下
在這裏插入圖片描述
type變成了ALL,這裏也說明了MySQL底層會自動進行類型轉換,隱性自動類型轉換,也是我們需要避免的。
字符串不加單引號還會導致一個很嚴重的問題,就是行鎖會升級爲表鎖。

8、 少用or

or也會導致索引失效。

 explain select * from staffs where name = 'July' or name = 'z3';

在這裏插入圖片描述
可見索引失效了。

9、

在這裏插入圖片描述

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