高性能Mysql讀後感(四)查詢優化

mysql 查詢執行的基礎

這裏寫圖片描述

語法解析器和預處理

* 解析器 *處理語法和解析查詢, 生成一課對應的 “解析樹”. —> mysql 語法層面 .

* 預處理器 * 進一步檢查解析樹的合法性. 如: 數據表和數據列 是否存在, 別名是否有歧義等, 還會進行權限認證.

查詢優化器

將 解析樹 轉換爲 執行計劃.

一條查詢可以有多種執行方式, 都會返回同樣的結果. 優化器的作用就是找到最好的執行計劃.
(當然也有可能做出最差的決定)

mysql 是基於成本的優化器, 其嘗試預測一個查詢使用某種執行計劃是的成本, 並選擇其中最小的那個.

導致 mysql 優化器選擇錯誤的執行計劃的原因.

  • 統計信息不準確. —> 如InnoDB 是不能提供準確的數據行數的.

  • 執行計劃中的成本估算不等同於實際執行的成本. 因爲執行計劃的成本 本來就是 “估算的”.

  • 優化器的”最優”, 和你的”最優” 可能不一樣. 一般希望的都是執行時間儘可能的短 = 最優. 但優化器不一定這麼認爲.

  • 不會考慮併發查詢的情況.

  • 有時候也不會去做基於成本的優化. 一些固定規則: 全文索引的 MATCH()字句. 如果相關列使用了全文索引,
    即是 使用別的索引 + where條件會快很多, 可 mysql 還是會使用 全文索引.

  • 不會考慮 存儲過程 和 用戶自定義函數 的成本.

  • 有時候, 可能無法算出所有的可能的執行計劃. 所有有可能錯過最優的執行計劃.(多表的關聯查詢等)

* 靜態優化 *

對解析樹進行分析優化. 比如將where條件做等價的變換, 或在where條件中帶入一些常數等.
靜態優化在第一次完成後就一直有效.

* 動態優化 *

動態優化和查詢的上下文有關, 如索引中條目對應的數據行數. 每次查詢的時候都需要重新獲取.

mysql 能夠處理的優化類型:

  • 重新定義關聯表的關聯順序
    mysql 並不總是按照查詢中指定的順序進行關聯查詢的.

  • 外鏈接 —> 內連接

  • 等價變換
    比如一堆 and < > 條件之間的關係

  • 優化 count(), min(), 和 max()
    例如 count(*): 找到某一列的最小值, 找到該列B-Tree索引最左端的記錄.

  • 預估並轉化爲常數表達式
    例如數學表達式等.

  • 覆蓋索引掃描
    當索引中的列包含查詢所需要的列時. mysql 就可以使用索引返回需要的數據, 不用再去查詢數據行.

  • 提前終止查詢
    滿足查詢的時候, 就會提前終止查詢. 如使用了 limit 的時候.

  • 等值傳播
    … join a.id = b.id where b.id > 20;
    ===> where a.id > 20 and b.id > 20;

  • IN()
    mysql 中 in() 不等於 多個or 當 in() 中的值比較多時, 速度會比 多個or 快.

執行計劃

是 mysql 生成的一顆指令書, 交給存儲引擎去處理,然後返回結果.

排序優化

如果 mysql 不能使用索引來排序的話, 那麼他會自己排序. filesort. 如果數據量小, 會在內存排序. 數據量大的話會使用磁盤. 但都是 filesort.

mysql 對每一個排序記錄都會分配一個足夠長的定長空間來存放. 這個空間大小 大於等於 其最長的字符串的大小.

** 對於關聯表的排序, 如果所有的排序列都是第一張表的話. mysql 會在關聯處理第一張表的時候就排序.
否則, 其他情況就是處理完所有的關聯表數據後,在排序. 此時會生成臨時表. 如果有Limit 那麼也會等拍完序之後再應用. 比如 取出了 1000條數據排序好了, 缺只要前20條數據. **

tips

* 關聯查詢 *

  • on 的字句上最好有索引
  • group by 和 order by 的列最好是在一張表.
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章