SQL優化 MySQL版 -分析explain SQL執行計划與Extra


Extra

作者 : Stanley 羅昊

轉載請注明出處和署名,謝謝!

注:此文章必須有一定的Mysql基礎,或觀看執行計划入門篇傳送門:

https://www.cnblogs.com/StanleyBlogs/p/10416865.html

終於總結到哦SQK執行計划的最后一個知識點了:

Extra

Extra有以下幾個值,它們都非常重要,它們表示你的SQL語句的最終性能,以下將介紹它的幾種值,每個值都代表你的SQL語句的缺陷:

1.Using filesort

主要出現在 order by 排序、復合索引跨列;

order by 排序

出現原因:查詢a表,卻根據b表排序,例如:

select * From test01 where a = '3' order by b;

如果避免此情況出現,就根據什么字段查,就根據什么字段進行排序。如:

select test01 where a = '3' order by a;

執行結果:

如果沒出現那就表明你這個SQL沒毛病很顯然上圖我沒出現👆,如果出現出現這個👇,說明你當前SQL語句需要“額外”的一次排序,我們理解起來就是,需要額外的一次查找;

假設我我們現在創建一張表test02,里面有 a1 a2 a3字段,然后分別給這三列字段添加索引;

這里我們就故意觸發一下:

select * From test01 where a = '1' order by b;執行結果如下:

講解:因為官方解釋說,你需要先查詢再排序假設你要根據b來排序,這個時候你不需要查,但是數據庫會自動的幫你查一下后再去排序,如果你自己在它排序之前已經查過了,那就不需要再去排序了,性能自然就高了,從頭到尾僅需一次查詢即可,如果你根據a查詢卻再讓跟b查詢,那必然需要查兩次,性能自然不高了;

所以先查詢,再排序就非常符合情理,性能自然高;

小結:對於單索引,如果排序和查找是同一個字段,則不會出現using filesort;如果排序和查詢不是同一個字段,那就會出現using filesort;

避免策略:你where那些字段,就order by那些字段~

復合索引跨列

不能跨列,舉例說明:

為了防止上面a b c單值索引的干擾,我們全部刪掉,建一個復合索引:

altet table test01 add a_b_c_index (a,b,c);

顯示所有索引:show index from 表名

執行結果:

首先a b c 這三個字段我都加了索引,然后我執行以下語句:

explain select * From test01 where a = 1 order by c;

很顯然,我跨列了,因為a b c 你中間跨了一個b,在復合索引下,必須要從左一次向右走,不得從中間往后,也不能跨列,否則就會出現Usein filesort;

我現在符合規范使用復合索引:

這樣就沒有出現Usein filesort,因為我沒有跨列;

避免策略:where 和 order by 按照復合索引的順序使用,不要跨列或無序使用

2.Useing temporary

主要出現在:group by分組中

它同樣也是性能損耗較大,用到了臨時表,如果在執行的時候出現了Useing temporary,它就不單單的在查你條件中的表,而又多出來了一張表,多了這張表,你的性能就必然損耗了;

其實跟上面那個Usein filesort有點相似:

select * From test01 where a in (1,2,3) group by a;

我根據a查詢,我又根據a分組,這樣就不會出現Useing temporary,這里我也不放圖了;

如果我非要讓他Useing temporary出現也不難,就把sql語句改成:

select * From test01 where a in (1,2,3) group by c;

我根據a查詢,卻根據c進行分組,這里Useing temporary必然會出現; 

道理很簡單:我查詢a,這個時候數據已經查出來了,我這時進行分組,就在你原查詢出來的數據上進行操作即可,但是如果你把a查出來的東西你不用,非要讓b進行分組,這個時候因為數據庫不知道b是誰,所以需要把b再查一遍出來放到臨時表進行排序;

避免Useing temporary策略:查詢那些列,就根據那些列進行分組 group by;

3.Using index

如果出現useing index,就表明這條sql性能提升了,看到它應該很高興;

這個詞兒(using index)翻譯過來應該是索引覆蓋,那么為什么性能就提升了呢?

原因在於:此次查詢,不讀取源文件,只從索引文件中獲取數據(不需要回表查詢);

什么是回表查詢?

講解:假設我建立一張表,這張表里面有id name age,我們假設根據age作為一個索引,比如說我現在寫一條語句:

select age From student where age = .....;

如果我這樣查詢,我們這個sql語句里面用到了age,但是age是我們定義好的索引,但是剛好我現在也只查age這個時候它就不需要查原表,只需要查索引表!

這個就被稱之為不需要回表查詢;

我們現在只查詢索引表,不查詢其他表那肯定就快了,因為:

我假設原表占了100M,但是索引表才占了1M,因為索引必定是一小部分,我們在1M里面查age,肯定比在100M里面查age要快許多;

如果我們只查age,age剛好也在索引里面,這個我就不需要在原表里面去查了,就稱之為不需要回表查詢 ,這種情況就會出現一Using index;

總結:只要使用到的列全部都在索引中,就是索引覆蓋 using index;

舉例:

這個時候我們表中有一個復合索引,a b c均為索引列:

現在我們編寫一條SQL語句:

原因很簡單,我需要查詢的列分別是 a b 但是a b這兩個列都在索引中,所以造成了索引覆蓋,結果就成了Using index;

4.Using where

需要回表查,在上面我講了Using index,是不需要回表查,至於什么是回表,我在上面寫的非常清楚!

既然需要回表,那就說明我們接下來我想要的數據既在原表中,也在索引中,這個時候就不得不導致需要回表查;

舉例:

假設 一張表中 age 是索引列,但是查詢語句 select age,name from 表名 where age = ...;

這條SQL語句很顯然,age在索引里面,但是name 不在索引里,這種情況就必須回原表,並且會顯示Using where;

SQL語句:EXPLAIN SELECT a,d FROM test01 where a = '';

執行結果:

a是索引列,b不是所以就必須回表查,就導致結果為Using where;

今日感悟:

智者:“為什么想走絕路?”;

年輕人:“我得不到別人的承認,沒有人欣賞並且重用我”

智者:“請你把我剛才仍在地上的那粒沙子撿起來”

年輕人:“這根本不可能”

智者:“那你能不能幫我把這里珍珠撿起來呢?”

年輕人:“當然可以”

智者:“你應該明白,現在你自己還不是一顆珍珠,所以你不能苛求別人立即認同你,如果要別人認同你,並且重用你,你就想辦法把自己變成那顆被我仍在地上的珍珠吧”


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM