記一次SQL調優


insert優化

如果你在某一時刻有大量的insert操作,一條一條插入是非常耗時的。insert語句本身支持一次插入很多條記錄,插入記錄數上限受sql語句長度限制,一般一次插個幾千條是沒問題的。在我的 《如何手動實現Try Insert和Insert Or Update》 一文中對於各種情況都有具體的例子,這里就不贅述了。

explain語句結果分析

SQL本身是一種對機器來說抽象級別很高的語言,我們通過SQL告訴DBMS我們需要什么,而沒有告訴它具體要怎么做。DBMS會猜測性地以最優的方法去完成我們給的任務,但是它往往做得不太好,畢竟不同業務最優做法各不相同,目前我們還沒有辦法讓機器完全理解我們的業務。所以我們需要輔助機器,幫助它找到最好的查詢邏輯。通常的做法是添加合適的索引,讓所有的查詢都走索引。在MySQL中,在任何一個select語句前加上explain,就可以知道MySQL對這條查詢的理解和實際執行邏輯。

下面來分析explain語句返回的結果。explain會展示查詢涉及到的每張表分析結果,里面有很多參數,我們一般只需要關注以下幾個參數:

  1. type

    type描述表是怎么join的,按從最好到最壞一共有以下幾個值:

    解釋
    system 表只有一行,是一種特殊的const type
    const 表里只有一行匹配的記錄,join時可以認為是常量
    eq_ref 使用的索引為primary keyunique not null index
    ref join只使用最左前綴匹配原則的普通索引
    fulltext 使用全文檢索索引
    ref_or_null ref差不多,主要是多了NULL值的查詢
    index_merge 使用了MySQL的索引合並優化
    unique_subquery 類似eq_ref,主要用於包含IN子查詢的查詢
    range 走索引的范圍查詢
    index 索引樹被整個掃了,速度比掃表好一點
    ALL 整個表被掃,非常糟糕的情況,一般要避免

    一般做SQL優化,通常出現indexALL都是需要優化的。

  2. Extra

    MySQL查詢的附件信息,有時候代表着查詢的額外代價,出現 Using filesortUsing temperary都表示查詢速度不行。

    • Using filesort表示order by子句不走索引,使用文件排序,需要對order by進行優化。
    • Using temperary表示查詢過程中創建了臨時表,通常發生在包含group byorder by的查詢中。
  3. rows和filtered

    rows表示MySQL預估的查詢需要的行數,filtered表示根據條件過濾之后的行所占的百分比。值為100表示沒有行被過濾掉。所以rows*filtered查詢需要的總的行數。這個值自然是越小越好。

查詢優化實踐

查詢優化的策略就是加索引,primary key 和 unique key在根據具體業務定,我們做優化,一般都是添加普通索引。普通索引分為兩種,單個字段的索引和多個字段的聯合索引。聯合索引的應用場景相對窄一點,如果你要查的數據可以被聯合索引全部囊括,直接從索引拿數據,可以考慮使用聯合索引。讀多寫少重復值少散列分布的字段最適合建索引。你可以把你的程序使用到的所有SQL都列出來,一條一條explain,沒有走索引的,就酌情給某個或某幾個字段(join里的字段、where里的字段都是重點考慮對象)加上索引,直到所有的查詢走索引為止。這么做以后,你的查詢type正常都可以到達比較好的情況,但是對於包含order by子句的查詢,可能你的Extra信息就不太理想了。Using filesortUsing temperary有時候陰魂不散,很難搞。這時候最佳的策略就是變着花樣選擇排序的字段。比如你的表有一個自增主鍵,你可以考慮用它作為插入時間來做排序。MySQL本身在這方面的優化非常糟糕,需要耐心地多嘗試。

Reference

MySQL explain

MySQL ORDER BY優化


免責聲明!

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



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