sql優化整理(一)

  sql的編寫語法是這樣的:mysql

SELECT DISTINCT 
	<select_list>
FROM 
	<left_table> <join_type> 
JOIN <right_table>	ON <join_condition>
WHERE 
	<where_condition>
GROUP BY 
	<group_by_list>	
HAVING 
	<having_condition>
ORDER BY 
	<order_by_condition>
LIMIT <limit_condition>

  

  MySQL讀取的順序是這樣的:ios

FROM <left_table>
ON <join_condition>
<join_type> JOIN <right_table>
WHERE <where_condition>
GROUP BY <group_by_list>
HAVING <having_condition>
SELECT
DISTINCT <select_list>
ORDER BY <order_by_condition>
LIMIT <limit_condition>

  

  

  MySQL官方對索引的定義:索引是幫助MySQL高效獲取數據的數據結構;索引的目的在於提升查詢效率,能夠相似字典;排好序的快速查找的數據結構;索引會影響where後面的查詢和order by後面的排序;通常來講索引自己也很大,不可能所有存儲在內存中,所以索引每每會以索引文件的形式存儲在磁盤上;頻繁增刪改的表不適合建索引;sql

 

  索引優點:數據庫

    提升數據檢索的效率,下降數據庫的IO成本;經過索引列對數據進行索引,下降數據排序的成本,下降CPU的消耗;緩存

  索引的劣勢:bash

    實際上索引也是一張表,該表保存了主鍵與索引字段,並指向實體表的記錄,因此索引列也是要佔用空間的;雖然索引大大提升了查詢速度,但會下降更新表的速度,如對錶進行INSERT,UPDATE和DELETE;由於更新表時,MySQL不只要保存數據,還要保存索引文件每次更新添加的索引列字段,都會調整由於更新所帶來的鍵值變化後的索引信息;服務器

  

  適合創建索引的狀況:數據結構

1.主鍵自動創建惟一索引
2.頻繁做爲查詢條件的字段應該創建索引
3.查詢中與其餘表關聯的字段,外鍵關係創建索引
4.頻繁更新的字段不適合創建索引,由於每次更新不單是更新了記錄還會更新索引結構;
5.where條件裏用不到的字段不建立索引
6.查詢中排序的字段,排序字段若經過索引去訪問將大大提升排序速度
7.查詢中統計或分組的字段

  

  不適合建立索引的狀況:性能

1.表記錄太少不適合創建索引;
2.常常增刪改的表不適合創建索引;提升了查詢速度,同時卻會更新表的速度,如對錶進行插入操做,由於更新表時,MySQL不只要保存數據,還要保存表的索引結構;
3.數據重複且分佈均勻的表的字段不適合創建索引,所以應該只爲最常常查詢的和最常常排序的數據創建索引;注意,若是某個數據列包含重複的內容,爲它創建的索引就沒有太大的效果;

  

 

  MySQL常見的性能瓶頸:優化

1.CPU:CPU在飽和的時候通常會發生在數據裝入內存或從磁盤上讀取數據時候
2.IO:磁盤I/O瓶頸發生在裝入數據遠大於內存容量的時候
3.服務器硬件的性能瓶頸:top, free, iostat和vmstat來查看系統性能狀態

  

  EXPLAIN用途:

1.表的讀取順序
2.數據讀取操做的操做類型
3.哪些索引可使用
4.哪些索引被實際使用
5.表之間的引用
6.每張表有多少行被優化器查詢

  

  EXPLAIN字段解釋:

    • id:select查詢的序列號,包含一組數字,表示查詢中執行select子句或操做表的順序

      三種狀況:

      • id相同,執行順序由上至下;
      • id不一樣,若是是子查詢,id的序號會遞增,id值越大優先級會越高,越先執行
      • id不一樣與不一樣,同時存在;id若是相同,能夠認爲是一組,從上往下執行;在全部組中,id值越大,優先級越高,越先執行;derived爲衍生,是臨時表,後面接數字對應相應的id;

 

    • select_type:查詢的類型,主要用於區別普通查詢,聯合查詢,子查詢等的複雜查詢(SIMPLE, PRIMARY, SUBQUERY, DERIVED, UNION, UNION RESULT);
      • SIMPLE:簡單的select查詢,查詢中不包含子查詢或UNION
      • PRIMARY:查詢中若包含任何複雜的子查詢,最外層查詢被標記爲PRIMARY
      • SUBQUERY:在SELECT或WHERE列表中包含了子查詢
      • DERIVED:在FROM列表中包含的子查詢被標記爲DERIVED(衍生),MySQL會遞歸執行這些子查詢,把結果放到臨時表中;
      • UNION:若第二個SELECT出如今UNION以後,則標記爲UNION;若UNION包含在FROM字句的子查詢中,外層SELECT將被標記爲DERIVED;
      • UNION RESULT: UNION操做的結果,id值一般爲NULL

 

    • table:顯示這一行的數據關於哪張表的

 

    • type:顯示查詢使用了哪一種類型,

      從最好到最差依次是:

        system>const>eq_ref>fulltext>ref_or_null>index_merge>unique_subquery>index_subquery>range>index>ALL

         system>const>eq_ref>ref>range>index>ALL

      • system:表只有一行記錄(等於系統表),這是const類型的特列,平時不會出現,這個也能夠忽略不計

      • const:表示經過索引一次就找到了,const用於比較primary key或unique索引,由於只匹配了一行數據,因此很快;若是將主鍵置於where列表中,MySQL就能將該查詢轉換爲一個常量

      • eq_ref:惟一性索引掃描,對於每一個索引鍵,表中只有一條記錄與之匹配;常見於主鍵或惟一索引;

      • ref:非惟一性縮影掃描,返回匹配某個單獨值的全部行;本質上也是一種索引訪問,它返回全部匹配某個單獨值的行,然而,它可能會找多個符合條件的行,因此它應該屬於查找和掃描的混合體;

      • range:只檢索給定範圍的行,使用一個索引來選擇行,key列顯示使用了哪一個索引;通常就是在where語句中出現了between,<,>,in等的查詢;這種範圍掃描索引比全表掃描要好,由於它只須要開始於索引的某一點,結束於某一點,不用掃描所有索引;

      • index:index與ALL區別爲index類型只遍歷索引樹;這一般比ALL快,由於索引文件一般比數據文件小(all和index都是讀全表,但index是從索引中讀取的,而all從硬盤中讀出來的)

      • all:將遍歷全表以找到匹配的行

 

    • possible_keys:顯示可能應用在這張表的索引,一個或多個,查詢涉及到的字段若存在索引,則該索引將被列出,但不必定被查詢實際使用;

 

    • key:實際使用的索引;若是爲NULL,則沒有使用索引;查詢中若使用了覆蓋索引,則該索引僅出現key列表中;

 

 

    • key_len:表示索引中使用的字節數,可經過該列計算查詢中使用的索引的長度;在不損失精度的狀況下,長度越短越好;key_len顯示的值爲索引字段的最大可能長度,並不是實際使用長度,即key_len是根據表定義計算而得,不是經過表內檢索出來的;

 

    • ref:顯示索引被哪一列使用,哪些列或者常量被用於查找索引上的值,其中const爲常量;

 

    • rows:根據表統計信息及索引選用狀況,大體估算出所需的記錄所須要讀取的行數

 

    • extra:包含不適合在其餘列顯示中顯示,但十分重要的額外信息
      • using filesort:說明mysql會對數據使用一個外部的索引排序,而不是按照表內的索引排序進行讀取;mysql中沒法利用索引完成的排序操做稱爲文件排序;

      • using temporary:使用了臨時表保存中間結果,mysql在對查詢結果排序時使用臨時表,經常使用於排序order by和分組查詢group by

      • using index:表示相應的select操做中使用了覆蓋索引,避免了訪問表的數據行;若是同時出現using where,代表索引被用來執行索引的鍵值查找;若是沒有同時出現using where,代表索引用來讀取數據而非執行查找操做;

        覆蓋索引的理解方式:

          1.select的數據列只用從索引列中就可以得到,沒必要讀取數據行,MySQL能夠利用索引返回select列表中的字段,而沒必要根據索引再次讀取數據文件;查詢列要被所建的索引覆蓋

          2.索引是高效找到行的一個方法,可是通常數據庫也能使用索引找到一個列的數據,所以它沒必要讀取整個行;畢竟索引葉子節點存儲了它們的索引數據,當能經過讀取索引就能夠獲得想到的數據,那就不須要讀取行,一個索引包含了(或覆蓋了)知足查詢結果的數據叫做覆蓋索引

          注意:若是要使用覆蓋索引,必定要注意select列表中只取出須要的列,不可select *,若是將全部字段一塊兒作索引會致使索引文件過大,查詢性能降低;

      • using where:代表使用where過濾

      • using join buffer:使用了鏈接緩存

        保證JOIN語句中被驅動表上JOIN條件字段已經添加索引;

         

        • 當使用left join時,左表是驅動表,右表是被驅動表

        • 當使用right join時,右表時驅動表,左表是被驅動表

        • 當使用join時,mysql會選擇數據量比較小的表做爲驅動表,大表做爲被驅動表

      • impossible where:where子句的值老是false,不能用來獲取任何元組

      • select tables optimized away:在沒有group by子句的狀況下,基於索引優化MIN/MAX操做或對於MyISAM存儲引擎優化COUNT(*) 操做,沒必要等到執行階段再進行計算,cha'x執行計劃生成的階段完成優化;

      • distinct:優化distinct,在找到第一匹配的元組後即中止找相同值的工做

相關文章
相關標籤/搜索