一腹纳、單表,多表查詢優(yōu)化:
多表查詢索引優(yōu)化:
JOIN 語句優(yōu)化:
二医舆、會導致索引失效的情況
1)俘侠、首先我們先建一個表;
CREATE TABLE `sys_user` (
`id` varchar(64) NOT NULL COMMENT '主鍵',
`name` varchar(64) DEFAULT NULL COMMENT '名字',
`age` int(64) DEFAULT NULL COMMENT '年齡',
`pos` varchar(64) DEFAULT NULL COMMENT '職位',
PRIMARY KEY (`id`),
KEY `idx_sys_user_nameAgePos` (`name`,`age`,`pos`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用戶表';
2)蔬将、常見的索引失效原因:
全值匹配:
違背最左前綴原則:
全值匹配意思就是聯(lián)立的復合索引的順序和個數要和檢索的條件順序和個數相同爷速。
最佳左前綴法則是指,如果索引了多列娃胆,要遵守最左前綴法則遍希。指的是查詢從索引的最左前列開始并且不跳過索引中的列
下面我們給這個表建立一個復合索引
ALTER TABLE sys_user ADD INDEX idx_sys_user_nameAgePos(name,age,pos);
以下是我們的檢索語句:
SELECT * FROM sys_user WHERE name='小明' AND age = 22 AND pos ='java';
我們通過在檢索語句前面加關鍵字 EXLAIN,可以知道是否使用的索引
EXPLAIN SELECT * FROM sys_user WHERE name='小明' AND age = 22 AND pos ='java';
EXPLAIN SELECT * FROM sys_user WHERE name='小明' AND age = 22 ;
EXPLAIN SELECT * FROM sys_user WHERE name='小明' AND pos ='java';
通過展示的結果我們可以知道里烦,第一個復合索引的三個字段我們都用了凿蒜,第二個復合索引我們只用到兩個字段禁谦,第三個復合索引我們只用到一個字段。三個語句我們都用到索引废封,顯然第一種是最優(yōu)的州泊。
我們再看看哪種情況會失效:
EXPLAIN SELECT * FROM sys_user WHERE age = 22;
EXPLAIN SELECT * FROM sys_user WHERE pos ='java';
EXPLAIN SELECT * FROM sys_user WHERE age = 22 AND pos ='java';
以上三種情況都變成了全表掃描,原因是違反了最左左前綴原則漂洋,因為復合索引最左邊的是name遥皂,當檢索條件name沒在前面索引將失效,第一種情況滿足了全值匹配刽漂,第二種滿足了兩個字段name和age演训,第三種因為只滿足了name,所以索引只用到name贝咙。
3)样悟、索引列上做計算、函數(自動或手動)類型轉換庭猩,會使索引失效轉為全表掃描
EXPLAIN SELECT * FROM sys_user WHERE LEFT(name,1)='小明';
第七種情況失效是因為索引列做了計算或者函數的操作窟她,導致了全表掃描。
4)蔼水、存儲引擎不能使用索引中范圍條件右邊的列
可能大家關看上面的文字不知道是什么意思震糖,下面我們執(zhí)行一下查詢語句就清楚了
EXPLAIN SELECT * FROM sys_user WHERE name='小明' AND age < 22 AND pos ='java';
從上圖我們可以知道type變成了范圍級別,也就是說age<22之后的pos字段的索引失效了趴腋。
**5)吊说、盡量使用覆蓋索引(只訪問索引的查詢(索引列和查詢列一致),減少select * 的使用 **
這個就是字面意思于样,查詢具體的字段比查詢*效率更高疏叨,下面我們坐一下對比
EXPLAIN SELECT * FROM sys_user WHERE name='小明' AND age =22 AND pos ='java';
EXPLAIN SELECT name,age,pos FROM sys_user WHERE name='小明' AND age =22 AND pos ='java';
6)潘靖、mysql在使用不等于(!= 或者<>)的時候無法使用索引會導致全表掃描
EXPLAIN SELECT * FROM sys_user WHERE name !='小明'
結果顯示索引失效導致了全表掃描
7)穿剖、is null,is not null 也無法使用索引
EXPLAIN SELECT * FROM sys_user WHERE name is not null
8)卦溢、like以通配符開頭(’%abc…’)mysql索引會失效變成全表掃描的操作糊余,(%寫右邊則可以避免索引失效,如果業(yè)務實在需要’%abc…%'則可以用覆蓋索引避免索引失效)
EXPLAIN SELECT * FROM sys_user WHERE name like '%明%'
EXPLAIN SELECT * FROM sys_user WHERE name like '明%'
EXPLAIN SELECT name,age,pos FROM sys_user WHERE name like '%明%'
從上面的結果单寂,第一種索引失效,第二種只寫右邊的%則可以避免索引失效宣决,第三種如果業(yè)務實在需要‘%abc…%’這種sql蘸劈,則可以用覆蓋索引解決索引失效的問題
9)、字符串不加單引號索引會失效
EXPLAIN SELECT * FROM sys_user WHERE name=222;
因為檢索字符串是必須加單引號贤惯,上面用用了222是int類型孵构,mysql在檢索的時候會判斷name是varchar的類型會將222轉換為’222’進行檢索雾袱,索引列發(fā)生了類型轉換叹俏,故索引失效蝌数。
10)、少用or,用它連接時會索引失效
EXPLAIN SELECT * FROM sys_user WHERE name='小明' or age = 22;
結論:
定值(常量const)垢乙、范圍(range之后是失效)、還是排序(最終看排序)骂倘,一般order by是給個范圍。
group by 基本上都需要進行排序荧库,會有臨時表產生。
一般性建議:
對于單鍵索引,盡量選擇針對當前Query過濾性更好的索引
在選擇組合索引的時候屎勘,當前Query中過濾性最好的字段在索引字段順序中,位置越靠前越好
在選擇組合索引的時候,盡量選擇可以包含當前Query中的where字句中更多字段的索引
盡可能通過分析統(tǒng)計信息和調整Query的寫法來達到選擇合適索引的目的