mysql學習(五)避免索引失效的一些原則

2022-05-06 07:36:06 字數 3839 閱讀 6034

a.復合索引,不要跨列使用或無序使用(遵循最佳左字首)

b.復合索引盡量使用全索引匹配

2.不要在索引上進行任何操作(計算、函式、型別轉換),否則索引失效

select ..where a.x = .. ;  --假設a.x是索引

不要:select ..where a.x*3 = .. ;

explain select * from book where authorid = 1 and typeid = 2 ;--用到了at2個索引

explain select * from book where authorid = 1 and typeid*2 = 2 ;--用到了a1個索引

explain select * from book where authorid*2 = 1 and typeid*2 = 2 ;----用到了0個索引

explain select * from book where authorid*2 = 1 and typeid = 2 ;----用到了0個索引,原因:對於復合索引,如果左邊失效,右側全部失效。(a,b,c),例如如果 b失效,則b c同時失效。

3.復合索引不能使用不等於(!=  <>)或is null (is not null),否則自身以及右側所有全部失效。復合索引中如果有》,則自身和右側索引全部失效。

explain select * from book where authorid = 1 and typeid =2 ;

-- sql優化,是一種概率層面的優化。至於是否實際使用了我們的優化,需要通過explain進行推測。

explain select * from book where authorid != 1 and typeid =2 ;

explain select * from book where authorid != 1 and typeid !=2 ;

體驗概率情況(< > =):原因是服務層中有sql優化器,可能會影響我們的優化。

drop index idx_typeid on book;

drop index idx_authroid on book;

alter table book add index idx_book_at (authorid,typeid);

explain select * from book where authorid = 1 and typeid =2 ;--復合索引at全部使用

explain select * from book where authorid > 1 and typeid =2 ; --復合索引中如果有》,則自身和右側索引全部失效。

explain select * from book where authorid = 1 and typeid >2 ;--復合索引at全部使用

----明顯的概率問題---

explain select * from book where authorid < 1 and typeid =2 ;--復合索引at只用到了1個索引

explain select * from book where authorid < 4 and typeid =2 ;--復合索引全部失效

--我們學習索引優化 ,是乙個大部分情況適用的結論,但由於sql優化器等原因  該結論不是100%正確。

--一般而言, 範圍查詢(> <  in),之後的索引失效。

4.盡量使用索引覆蓋(using index)

索引(a,b,c) select a,b,c from xx..where a=  .. and b =.. ;

5.like盡量以「常量」開頭,不要以'%'開頭,否則索引失效

select * from xx where name like '%x%' ; --name索引失效

explain select * from teacher  where tname like '%x%'; --tname索引失效

explain select * from teacher  where tname like 'x%';

explain select tname from teacher  where tname like '%x%'; --如果必須使用like '%x%'進行模糊查詢,可以使用索引覆蓋 挽救一部分。

6.盡量不要使用型別轉換(顯示、隱式),否則索引失效

explain select * from teacher where tname = 'abc' ;

explain select * from teacher where tname = 123 ;//程式底層將 123 -> '123',即進行了型別轉換,因此索引失效

7.盡量不要使用or,否則索引失效

explain select * from teacher where tname ='' or tcid >1 ; --將or左側的tname 失效。

8.一些其他的優化方法

(1)exist和in選擇

select ..from table where exist (子查詢) ;

select ..from table where 字段 in  (子查詢) ;

如果主查詢的資料集大,則使用in   ,效率高。

如果子查詢的資料集大,則使用exist,效率高。    

exist語法: 將主查詢的結果,放到子查需結果中進行條件校驗(看子查詢是否有資料,如果有資料 則校驗成功), 如果符合校驗,則保留資料;

select tname from teacher where exists (select * from teacher) ;

--等價於select tname from teacher

select tname from teacher where exists (select * from teacher where tid =9999) ;   

in:

select ..from table where tid in  (1,3,5) ;

(2)order by 優化

using filesort 有兩種演算法:雙路排序、單路排序 (根據io的次數)

mysql4.1之前 預設使用 雙路排序;雙路:掃瞄2次磁碟(1:從磁碟讀取排序字段 ,對排序字段進行排序(在buffer中進行的排序)   2:掃瞄其他字段 ) --io較消耗效能

mysql4.1之後 預設使用 單路排序  : 只讀取一次(全部字段),在buffer中進行排序。但種單路排序 會有一定的隱患 (不一定真的是「單路|1次io」,有可能多次io)。原因:如果資料量特別大,則無法 將所有欄位的資料 一次性讀取完畢,因此 會進行「分片讀取、多次讀取」。

注意:單路排序 比雙路排序 會占用更多的buffer。

單路排序在使用時,如果資料大,可以考慮調大buffer的容量大小:  set max_length_for_sort_data = 1024  單位byte

如果max_length_for_sort_data值太低,則mysql會自動從 單路->雙路   (太低:需要排序的列的總大小超過了max_length_for_sort_data定義的位元組數)

提高order by查詢的策略:

a.選擇使用單路、雙路 ;調整buffer的容量大小;

b.避免select * ...  

c.復合索引 不要跨列使用 ,避免using filesort

d.保證全部的排序字段 排序的一致性(都是公升序 或 降序)

避免索引失效

1.全值匹配,對索引中所有列都指定具體值。2.最左字首法則,如果索引有多列,要遵循最左字首法則。指的是查詢從索引的最左前列開始,並且不跳過索引中的列。否者不走索引。3.範圍查詢右邊的列,不走索引,應為mysql底層範圍查詢之後結構就斷了,就無法使用後面得索引了。4.不要在索引列上進行運算操作,索引將...

Mysql的索引失效(應避免)(十)

type system const eq ref ref range index all 一般來說 查詢要達到index級別,最好能達到ref 案例1 create index girl cup money on girl age,cup size,money show index from gir...

MySQL 中索引優化(即避免索引失效)

全值匹配 查詢欄位按順序在索引中都可以找到。最左字首法則 查詢欄位與索引欄位不同時,會導致索引失效,即如果索引了多列,則查詢欄位從索引最左前列開始,不要跳過已有索引列。不要再索引上做任何計算 包括計算 函式 自動或手動 型別轉換。索引列上不能有範圍 將可能做範圍查詢的字段放在索引順序的最後。盡量使用...