explain字段可以分優(yōu)先順序看,但是要結(jié)合著看舰攒。
一败富、字段
【type】:查詢計劃對某個表的查詢方式,表示關(guān)聯(lián)類型或訪問類型摩窃,即MySQL決定如何查找表中的行兽叮,查找數(shù)據(jù)行記錄的大概范圍
依次從最優(yōu)到最差分別為:system > const > eq_ref > ref > range > index > ALL
一般來說,得保證查詢達(dá)到range級別猾愿,最好達(dá)到ref鹦聪。
NULL:
system:? 表數(shù)據(jù)只存在一條出現(xiàn)該屬性值;表中只有一條數(shù)據(jù)蒂秘,這個類型是特殊的?const?類型泽本。
const:? ?查詢條件只使用唯一索引(索引列值是唯一的),且最終結(jié)果只有一條記錄(索引只掃描一次)姻僧;(比較理想的狀態(tài))
表連接情況下规丽,使用連接字段為唯一索引蒲牧,且最終連接結(jié)果只有一條結(jié)果匹配(索引只掃描一次);
eq_ref:與const一樣赌莺,只使用唯一索引冰抢,但是匹配結(jié)果是多條;
ref:查詢條件或者連接條件出現(xiàn)非唯一索引艘狭;(比較經(jīng)晨嫒牛看到的是這個)
range:查詢條件索引字段出現(xiàn)范圍查詢,如in,or等缓升;這個類型通常出現(xiàn)在 =, <>, >, >=, <, <=, IS NULL, <=>, BETWEEN, IN() 操作中鼓鲁。
index:使用到了索引,即為index港谊;type=index 執(zhí)行效率僅高于全表掃描骇吭,是掃描了全部索引后才完成的操作,在某些情況下比全部掃描更差歧寺。key_len比較大燥狰,說明索引太長。
All:沒有索引或全表掃描斜筐。全表掃描龙致,MYSQL掃描全表來找到匹配的行。
【possible_keys】:查詢時可能使用到哪些索引顷链。
explain 時可能出現(xiàn) possible_keys 有列目代,而 key 顯示 NULL 的情況,這種情況是因為表中數(shù)據(jù)不多嗤练,mysql認(rèn)為索引對此查詢幫助不大榛了,選擇了全表查詢。
【key】:實際上使用到的索引煞抬。
【key_len】:顯示了mysql在索引里使用的字節(jié)數(shù)霜大,通過這個值可以算出具體使用了索引中的哪些列。
這一列顯示mysql實際采用哪個索引來優(yōu)化對該表的訪問革答。如果沒有使用索引战坤,則該列是 NULL。如果想強(qiáng)制mysql使用或忽視possible_keys列中的索引残拐,在查詢中使用 force index途茫、ignore index。
【ref】:在key列記錄的索引中蹦骑,表查找值所用到的列或常量慈省,常見的有:const(常量),字段名。
【rows】:掃描出的行數(shù)(很有參考意義)边败,這個是個估算的值袱衷,并不是真正的結(jié)果集。(mysql估計要讀取并檢測的行數(shù)笑窜,注意這個不是結(jié)果集里的行數(shù)致燥。)
【Extra】:展示的是額外信息。Extra排截,主要看使用 order by 進(jìn)行排序時有沒有出現(xiàn) Using filesort 和 Using index嫌蚤。
盡量通過 order by 和 where 配合,可以出現(xiàn) Using index断傲。避免 Using filesort脱吱。
那么什么時候會出現(xiàn) Using index 呢?order by 語句滿足索引最左前綴认罩,where 和 order by 條件列組合滿足索引最左前綴箱蝠。
Using index:表示使用了覆蓋索引,速度比較快垦垂。
Using where:使用 where 語句來處理結(jié)果宦搬,并且查詢的列未被索引覆蓋。(這種情況一般需要優(yōu)化了)劫拗。
Using index condition:查詢的列不完全被索引覆蓋间校,where條件中是一個前導(dǎo)列的范圍。
Using temporary:mysql需要創(chuàng)建一張臨時表來處理查詢页慷。(出現(xiàn)這種情況一般是要進(jìn)行優(yōu)化的)憔足,首先是想到用索引來優(yōu)化。
Using filesort:將用外部排序而不是索引排序酒繁,數(shù)據(jù)較小時從內(nèi)存排序四瘫,否則需要在磁盤完成排序。(這種情況下一般也是要考慮使用索引來優(yōu)化的欲逃。)
Select tables optimized away:使用某些聚合函數(shù)(比如 max、min)來訪問存在索引的某個字段饼暑。
二稳析、小記
1、不同的表數(shù)據(jù)對同一個sql可能explain的結(jié)果會不一樣弓叛,因為在不強(qiáng)制的情況下MySQL一般都有自己的想法選擇索引彰居;
2、通常情況下 等值匹配的索引命中理論上只要符合 左側(cè)原則等即可撰筷,如過非等值匹配則另說陈惰。特別是 帶有order by 條件的語句需要視情況配合where設(shè)置為組合索引才能生效。
如:select * from? tbname? ? where? A=1 and? B!=2? and? addTime<'20100305' order by addTime desc limit 1;
雖然此時很可能type=ref毕籽,但是Extra是Using where抬闯;Using filesort等井辆。此時并不代表索引OK。
若此時索引為 A溶握,addTime杯缺。則Using where還可能Using filesort。要特別注意睡榆,帶 order by的語句如果不是和where 組合索引而是各自字段索引很可能就是Using filesort萍肆,需要優(yōu)化。通常我們會誤以為 對where和order by 的各自字段單獨(dú)建立索引就可以命中的胀屿。
若此時索引為 (A塘揣,addTime)。則Using where宿崭。此時應(yīng)該關(guān)注 A字段索引是否是可以查一條亲铡,即rows=1。當(dāng)A基本為相同值時劳曹,例如日期奴愉,但是同一日期的數(shù)據(jù)有可能幾十萬條時,則說明rows約等于幾十萬铁孵,也就是要掃描這么多數(shù)據(jù)锭硼,則索引索引命中但基本不發(fā)揮作用,應(yīng)優(yōu)化蜕劝。
鑒于A字段建立的索引基本是相同值檀头,所以考慮將A索引棄用♂妫考慮調(diào)整為where? B!=2? and addTime<'20100305' order by addTime desc limit 1;? 若此時索引為addTime字段暑始。一般情況下,此時會用上索引 addTime但是有可能因為 addTime<'20100305' 條件又要掃描上千萬條數(shù)據(jù)中去找? 降序的最上面一條婴削。也不合理廊镜。
最終,where? B!=2? order by addTime desc limit 1; 且若此時索引為addTime字段唉俗,則命中索引addTime且rows=1嗤朴,這樣才行。才不會慢查詢虫溜。
其他參考資料: