MySQL之查詢性能優化一

只有當查詢優化,索引優化,庫表結構優化齊頭並進時,才能實現mysql高性能。mysql

在嘗試編寫快速的查詢以前,須要清楚一點,真正重要是響應時間。sql

 

查詢的生命週期數據庫

一般來講,查詢的生命週期大體能夠按照順序來看:從客戶端->服務器->而後再服務器上進行解析->生成執行計劃->執行->並返回結果給客戶端。緩存

其中"執行"能夠認爲是整個生命週期最重要的階段,這其中包括了大量爲了檢索數據到存儲引擎的調用以及調用後的數據處理,包括排序,分組等。服務器

對於一個查詢的所有生命週期,上面列的並不完整。這裏咱們只是想說:瞭解查詢的生命週期,清楚查詢的時間消耗狀況對於優化查詢有很大的意義。mysql優化

 

慢查詢基礎:優化數據訪問post

  1.是否向數據庫請求了不須要的數據性能

  2.mysql是否掃描額外的紀錄優化

    查詢是否掃描了過多的數據。最簡單的衡量查詢開銷三個指標以下:spa

      響應時間。

      掃描的行數。

      返回的行數。

    沒有哪一個指標可以完美地衡量查詢的開銷,但它們大體反映了mysql在內部執行查詢時須要多少數據,並能夠推算出查詢運行的時間。

    這三個指標都會記錄到mysql的慢日誌中,因此檢查慢日誌記錄是找出掃描行數過多的查詢的好辦法。

    響應時間:

      是兩個部分之和:服務時間和排隊時間。

       服務時間是指數據庫處理這個查詢真正花了多長時間。

       排隊時間是指服務器由於等待某些資源而沒有真正執行查詢的時間。---多是等io操做完成,也多是等待行鎖,等等。

    掃描的行數和返回的行數:

      分析查詢時,查看該查詢掃描的行數是很是有幫助的。這在必定程度上可以說明該查詢找到須要的數據的效率高不高。

    掃描的行數和訪問類型:

      在expain語句中的type列反應了訪問類型。訪問類型有不少種,

      從全表掃描(ALL)到

       索引掃描(index)到

       範圍掃描()到

       惟一索引查詢 到

       常數引用等。這裏列的這些,速度由慢到快,掃描的行數也是從小到大。

    若是發現查詢須要掃描大量的數據但只返回少數的行,那麼一般能夠嘗試下面的技巧去優化它:

      使用索引覆蓋掃描。

      改變庫表結構。例如使用單獨的彙總表。

      重寫這個複雜的查詢。讓mysql優化器可以以更優化的方式執行這個查詢。

 

一些簡單的重構查詢的方式:

  1.一個複雜查詢 or 多個簡單查詢

    設計查詢的時候一個須要考慮的重要問題是,是否須要將一個複雜的查詢分紅多個簡單的查詢。

  2.切分查詢

    有時候對於一個大查詢咱們須要「分而治之」,將大查詢切分爲小查詢,每一個查詢功能徹底同樣,只完成一小部分,每次

    只返回一小部分查詢結果。

  3.分解關聯查詢

    select * from tag 

       join tag_post on tag_post.tag_id = tag.id

       join post on tag_post.post_id = post.id

    where tag.tag = 'mysql'

    能夠分解成下面這些查詢來代替:

    > select * from tag where tag = 'mysql'

    > select * from tag_post where tag_id = 1234

    > select * from post where post_id in (123, 456, 567, 9098, 8904)    

  優點:

      讓緩存的效率更高。

      將查詢分解後,執行單個查詢能夠減小鎖的競爭。

      在應用層作關聯,能夠更容易對數據庫進行拆分,更容易作到高性能和可擴展。

      查詢自己效率也可能會有所提高。

      能夠減小冗餘記錄的查詢,

      更進一步,這樣作至關於在應用中實現了哈希關聯,而不是使用mysql的嵌套循環關聯。

 

查詢主流程:

  當但願mysql可以以更高的性能運行查詢時,最好的辦法就是農清楚mysql是如何優化和查詢的。

  一旦理解這一點,不少查詢優化工做實現上就是遵循一些原則讓優化器可以按照預想的合理的方式運行。

  

1.客戶端發送一條查詢給服務器

2.服務器先檢查查詢緩存,若是命中了緩存,則馬上返回存儲在緩存中的結果,不然進入下一階段。

3.服務器進行SQL解析,預處理,再由優化器生成對應的執行計劃,

4.mysql根據優化器生成的執行計劃,調用存儲引擎的API來執行查詢。

5.將結果返回給客戶端。

 

MySQL鏈接狀態:

對於一個MYSQL鏈接,或者說一個線程,任什麼時候刻都有一個狀態,該狀態表示了mysql正在作什麼,有不少方式能查看當前
狀態,最簡單的是使用show full processlist
在一個查詢的週期中,狀態可能會變化不少次,
這些狀態有:
  sleep:
  線程正在等待客戶端發送新的請求。

  query:
  線程正在執行查詢或者正在將結果發送給客戶端。

  locked:
  在mysql服務器層,該線程正在等待表鎖。在存儲引擎級別實現的鎖,
  例如innoDB的行鎖,並不會體如今線程狀態中。對於myisam來講這是個比較典型的狀態,但在其餘沒有
  行鎖的引擎也常常會出現。

  analyzing and statistics:
  線程正在收集存儲引擎的統計信息,並生成查詢的執行計劃。

  copying to tmp table [on disk]:
  線程正在執行查詢,而且將結果集複製到一個臨時表,
  這種狀態通常要麼是在作 group by 操做,要麼是文件排序操做,或者是union操做
  若是這個狀態後面還有 on disk 標記,那表示mysql正在將一個內存臨時表放到磁盤上。

  sorting result:
  線程正在對結果集進行排序

  sending data:
  這表示多種狀況,線程可能在多個狀態之間傳送數據,或者在生成結果集,或者在客戶端發送請求。

 

 

總結:

  本文主要介紹了一些關於mysql的查詢流程和一些基本術語,這些對理解mysql優化查詢會有至關大的幫助。

相關文章
相關標籤/搜索