做爲一個後端程序員,數據庫這個東西是繞不開的,特別是寫sql的能力,若是您參加過屢次面試,那麼必定會從面試覆盤中發現面試官老是會考察到sql優化這個東西。mysql
我在以前的屢次面試中最常遇到的一個問題的sql優化,不管是大廠仍是小廠。但我以前沒有詳細去了解過這些東西啊,我就瞎雞兒吹了,畢竟我也幹過兩三年的crud,sql仍是寫過很多的,也遇到過一些特別長的sql,執行時間特別長的sql,因此之前常常犧牲午睡時間給客戶出報表仍是有點效果的,mmp的。程序員
我是這樣說的:Sql優化,首先就是看sql的執行計劃,而後按照執行計劃對應的執行修改,好比該建索引建索引,而後就balabala....面試
其實老子以前壓根就沒學過怎麼看執行計劃,純靠這麼些年寫sql的經驗瞎雞兒吹。這也是上個月開始看MySqL,才學會看,那今天就現學現賣,給您們展現兩下子。sql
一、如何查看sql的執行計劃數據庫
在須要執行的查詢SQL前添加一個關鍵字「EXPLAIN」後端
從上圖能夠看到,執行計劃共有12字段,先來簡便看每一列的做用:緩存
字段解釋idselect查詢的序列號,包含一組數字,表示查詢中執行select子句或操做表的順序select_type查詢類型table訪問到的表partitions匹配的分區type訪問類型possible_keys有可能會使用到的索引key實際使用到的索引,若是爲NULL,則沒有使用索引key_len索引中使用的字節數,可經過該列計算查詢中使用的索引長度ref顯示索引的哪一列被使用了rows估算找到所需數據需讀取的行數filtered查詢的錶行佔表的百分比extra包含不適合在其餘列展現但異常重要的信息,好比是使用索引排序仍是文件排序bash
二、EXPLAIN中的列優化
(1)id編碼
一、標識select所屬的行,sql語句中有多少個select就有多少個id,而且id的順序是按照select出現的順序增加的
二、id越大,越先執行
三、id相同,從上往下執行
四、id爲NUll的最後執行
例如:(1)id相同,從上往下依次執行
explain select * from student,class,class_student;
(2)id不一樣,id越大執行優先級越高
explain select s.id,s.name,(select 1 from class) from student s;
(3)id相同又不一樣,id越大越先執行,id相同從上往下執行
explain select id,name from student where id <5 union select s.id,s. name from student s,class_student cs where cs.stu_id = s.id and cs.class_id = 4;
(2) select_type
顯示對應行是簡單仍是複雜select,SIMPLE值代表沒有子查詢或Union,若是有子查詢,那麼最外層標記爲Primary
(1)SUBQUERY 包含在select字段中的子查詢,不在From語句中 例如:
explain select id,name,(select class_id from class_student) from student;
(2)DERIVED 包含在From中的子查詢,MySQL會遞歸執行並將結果放在一個臨時表中,成爲派生表,從子查詢中派生出來的。
(3)UNION 在UNION中的第二個和隨後的select被標記爲UNION。第一個select被標記爲外查詢來執行,若是UNION被From子句中的子查詢包含,那麼它的第一個Select會被標記爲DERIVED。
explain select id,name from student where id>5 union select id,name from student where id>15;
UNION被包含在From子句中的示例:
explain select * from ( select id,name from student where id>15 union select id,name from student where id<4 ) a;
(4)UNION RESULT 用來從UNION的匿名臨時表檢索結果的select被標記爲UNION RESULT。上例中能夠看到
(5)DEPENDENT select依賴於外層查詢中發現的數據。
explain select s.id,s.name,(select class_id from class_student cs where cs.stu_id = s.id) from student s;
(6)UNCACHEABLE select中的某些特性阻止結果被緩存在一個Item_cache中。
(3) table
顯示當前行的數據來自於哪一張表
(4)type
訪問類型,結果值從好到壞依次是:NULL>system>const>eq_ref>ref>range>index>ALL
通常來講,保證查詢至少能到達range級別,最好能達到ref。
(1)system 表中只有一行數據(系統表)
(2)const 經過索引一次就能找到的數據,好比primary key 和union key,主鍵在where條件中,就能將查詢轉換成一個常量。好比:student表中id是主鍵
explain select * from student where id = 1;
(3)eq_ref 惟一性索引掃描,對於每一個索引鍵,表中只有一條記錄與之匹配。常見於主鍵或惟一索引掃描。
explain select * from student s left join (select * from class_student where stu_id > 10)cs on cs.stu_id = s.id where cs.class_id = 4;
(4)ref 非惟一性索引掃描,返回匹配某個單獨值得全部行 好比:student表中的age是一個普通索引
explain select * from student where age = 20;
(5)range
一、只檢索給定範圍的行,使用一個索引來選擇行,key列顯示使用了哪一個索引
二、通常就是where條件中出現「>」、「<」、「between」、「in」等條件
三、這種範圍掃描索引掃描比全表掃描要好,由於它只須要開始於索引的某一點,而結束語另外一點,不用掃描所有索引。
例如:
explain select * from student where id > 5;
(6) All 全表掃描,不使用任何條件或索引。好比:student表中score字段是沒有設置索引的。
(5)possible_keys
可能會使用到的key
(6)key
實際使用到的key
(7)key_len
索引中使用的字節數,可經過該列計算出使用的是哪些列,長度越短越好。顯示的是索引字段的最大可能長度,並不是實際使用長度,根據表定義計算而來,不是經過表內檢索而來。
須要注意的是:一、char字段一個字符在utf8編碼下最多佔3個字節,可變長字段須要額外的兩個字節記錄長度,外加須要存入一個null值,一個null是一個字節 二、複合索引有最左前綴的特性,若是複合索引能所有使用上,則是複合索引字段的索引長度之和,這也能夠用來斷定複合索引是否部分使用,仍是所有使用。
好比:student表的id是int類型,四個字節,因此key_len是4
explain select * from student where id > 5;
name字段類型是varchar(20),因此ken_len=20*3+2+1=63
EXPLAIN select * from student where name = '張三';
(8)ref
顯示索引的哪一列被使用了,若是可能的話,是一個常數。哪些列或者常量被用於查找索引列上的值。
explain select * from student s,class_student cs where cs.stu_id=s.id and cs.class_id = 4;
從第二行可知,使用了student表中的主鍵查詢,ken_len爲4 ref爲test.cs.stu_id代表使用了cs表中的stu_id字段。
(9) rows
根據表統計信息及索引選用狀況,大體估算出找到所需的記錄須要讀取的行數。
(10)extra
值描述Using filesort說明mysql會對數據使用一個外部的索引排序,而不是按照表內的索引順序進行讀取。MySQL中沒法利用索引完成的排序操做稱爲"文件排序"Using temporary使了用臨時表保存中間結果,MySQL在對查詢結果排序時使用臨時表。常見於排序 order by 和分組查詢 group by。Using index表示相應的select操做中使用了覆蓋索引(Covering Index),避免訪問了表的數據行,效率不錯! 若是同時出現using where,代表索引被用來執行索引鍵值的查找; 若是沒有同時出現using where,代表索引用來讀取數據而非執行查找動做Using where使用了where條件Using join buffer使用了鏈接緩存impossible wherewhere子句的值老是false,不能用來獲取任何元素distinct一單mysql找到了與形相聯合匹配的行,就不在搜索了
注意:當在Extra列出現了Using filesort時候,就說明能夠創建相應的索引進行排序優化查詢了。
下面是一個完整的思惟導圖:
===============================
我是Liusy,一個喜歡健身的程序員。
獲取更多幹貨以及最新消息,請關注公衆號:上古僞神
若是對您有幫助,點個關注就是對我最大的支持!!!
結尾小驚喜:公衆號回覆「MySQL」,送您一個MySQL的總體思惟導圖。