面試官:不會sql優化?出門右轉順便帶上門,謝謝

導讀

做爲一個後端程序員,數據庫這個東西是繞不開的,特別是寫sql的能力,若是您參加過屢次面試,那麼必定會從面試覆盤中發現面試官老是會考察到sql優化這個東西。mysql

我在以前的屢次面試中最常遇到的一個問題的sql優化,不管是大廠仍是小廠。但我以前沒有詳細去了解過這些東西啊,我就瞎雞兒吹了,畢竟我也幹過兩三年的crud,sql仍是寫過很多的,也遇到過一些特別長的sql,執行時間特別長的sql,因此之前常常犧牲午睡時間給客戶出報表仍是有點效果的,mmp的。程序員

我是這樣說的:Sql優化,首先就是看sql的執行計劃,而後按照執行計劃對應的執行修改,好比該建索引建索引,而後就balabala....面試

其實老子以前壓根就沒學過怎麼看執行計劃,純靠這麼些年寫sql的經驗瞎雞兒吹。這也是上個月開始看MySqL,才學會看,那今天就現學現賣,給您們展現兩下子。sql

SQL執行計劃(以MySQL爲例)

一、如何查看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的總體思惟導圖。

相關文章
相關標籤/搜索