MySQL學習筆記——查詢性能優化

查詢性能優化

  • 查詢性能優化主要從查詢優化、索引優化、庫表結構優化三個方面出發

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

查詢性能低下最根本的原因就是訪問的數據太多,大部分性能低下的查詢都可以通過減少訪問的數據量進行優化。

一般有效的分析步驟如下:

  • 確認應用程序是否在檢索大量超過需要的數據。這通常意味着訪問了太多的行,也有可能是訪問了太多的列。
  • 確認MySQL服務器層是否在分析大量超過需要的數據行。

    1. 是否向數據庫請求了不需要的數據

    有些查詢會請求超過實際需要的數據,然後這些多餘的數據會被應用程序捨棄掉。這會給MySQL服務器帶來額外的負擔,並增加網絡開銷,另外也會消耗應用服務器的CPU和內存資源

    1. 是否掃描了額外的數據

    如果發現查詢需要掃描大量的數據但只返回少數的行,那麼通常可以嘗試以下技巧來優化:

    • 使用索引覆蓋掃描,把所有需要用到的列都放到索引中。
    • 改變庫表結構。
    • 重寫這個複雜的查詢。

重構查詢

優化有問題的查詢時,目標應該是找到一個更優的方法獲取實際需要的數據,而不是一定總是從MySQL獲取一模一樣的結果集。

  • 複雜查詢與簡單查詢:設計查詢的時候需要考慮,是否將一個複雜查詢分成多個簡單查詢。
  • 切分查詢:將大查詢切分成小查詢,每次只返回一小部分查詢結果
  • 分解關聯查詢:簡單說就是,可以對每一個表進行一次 單表查詢,然後將結果在應用程序中進行關聯。

優點: - 緩存效率更高。許多應用程序可以方便地緩存單表查詢對應的結果。 - 將查詢分解後,執行單個查詢可以減少鎖的競爭。 - 查詢本身的效率也可能有所提升。 - 在應用層做關聯,可以更容易的對數據進行拆分,更容易做到高性能和可擴展。 - 可以減少冗餘記錄的查詢。

查詢執行的過程

  • 從客戶端向服務器請求數據,如果查詢語句在緩存中命中(這個過程是通過大小寫敏感的哈希值查找來實現)則直接從緩衝中取出結果;否則進入下一階段
  • 服務器端進行SQL解析、預處理、再由優化器生成對應的執行計劃
  • 根據優化器生成的執行計劃,調用存儲引擎的API來執行查詢
  • 將結果返回給客戶端

總結一些常用的sql優化方法

再整理

查詢優化器

優化策略分爲兩種:一是靜態優化,二是動態優化。靜態優化是直接對解析樹進行分析,並完成優化。靜態優化不依賴於特別的數值。靜態優化在第一次完成後就一直有效,是一種“編譯時優化”。動態優化則和查詢的上下文有關,是一種“運行時優化”。MySQL對查詢的靜態優化只需要做一次,但對查詢的動態優化則在每次執行時都需要重新評估。

MySQL能處理的查詢類型:

  • 重新定義關聯表的順序
  • 將外鏈接轉化爲內連接
  • 使用等價變換規則
  • 優化COUNT()、MIN()和MAX()
  • 預估並轉化爲常數表達式
  • 覆蓋索引掃描
  • 子查詢優化
  • 提前終止查詢
  • 等值傳播
  • 列表IN()的比較:MySQL會對IN列表進行排序,再使用二分查找,查找速度更快。

排序優化

排序是一個成本很高的操作,所以從性能上考慮,應儘可能避免排序或者儘可能避免對大量數據進行排序。MySQL可以通過索引進行排序,當不能使用索引生成排序結果時,則需要MySQL自己排序。

MySQL兩種排序算法:

  • 兩次傳輸排序(舊版本)

    讀取行指針和需要排序的字段,對其進行排序,然後再根據排序結果讀取所需要的數據行。兩次數據傳輸的成本非常高。

  • 單次傳輸排序(新版本)

    先讀取查詢所需要的所有列,然後再根據給定列進行排序,最後直接返回排序結果。

MySQL對count()查詢的優化

COUNT()有兩種不同的作用:統計某個列值的數量(COUNT(col)),或者可以統計結果集的行數(COUNT(*))。在統計列值時要求列值是非空的(即不統計值爲NULL的行)。在執行COUNT()的時候,通配符並不會擴展成所有列,實際上,它會忽略所有的列而直接統計行數。

MyISAM的COUNT()函數執行的非常快,但這是有前提的,即如果沒有任何WHERE條件,MyISAM的COUNT()纔會非常快。因爲此時無須實際的去遍歷表來獲得行數,MySQL可以利用MyISAM存儲引擎的特性來直接獲得這個值(MyISAM會存儲表的行數)。如果MySQL知道某列col非空,則MySQL內部會將COUNT(col)優化爲COUNT(*)。

當統計帶有WHERE子句的行數時,MyISAM的COUNT()和其它存儲引擎沒有任何區別,都需要遍歷整張表。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章