從宏觀上談mysql查詢優化

在之前一次大數據技術分享(大數據-Apache Kylin 2.5更智能、更敏捷、更易用的OLAP引擎)中,有一頁的ppt是這樣講sql優化的,有些感觸現分享出來。SQL語句的邏輯處理順序,指的是SQL語句按照一定的規則,一整條語句應該如何執行,每一個關鍵字、子句部分在什麼時刻執行。除了邏輯順序,還有物理執行順序。物理順序是SQL語句真正被執行時的順序(執行計劃),它是由各數據庫系統的關係引擎中的語句分析器、優化器等等組件經過大量計算、分析決定的。

通常一般人談起mysql查詢優化,侃侃而談。其實很多人都忽略了這樣的一個問題,mysql的邏輯執行順序是什麼樣子的。

以下是對上述邏輯執行順序的描述:

  1. .首先從FROM語句中獲取要操作的表並計算笛卡爾積。如果有要聯接的表,則還獲取聯接表。對它們計算笛卡爾積,笛卡爾積的結果形成一張虛擬表vt1。這裏就體現了物理順序和邏輯順序的一個不同點:按照邏輯順序,在執行SQL語句之初總是會進行笛卡爾積的計算,如果是兩張或多張非常大的表,計算笛卡爾積是非常低效的行爲,這是不能容忍的。所以物理順序會進行一些優化決定,比如使用索引跳過一部分或整個笛卡爾積讓計算變得很小。
  2. .對虛擬表vt1執行ON篩選語句,得到虛擬表vt2。
  3. .根據聯接類型,將保留表的外部行添加到vt2中得到虛擬表vt3。
  4. .對vt3執行where條件篩選,得到虛擬表vt4。
  5. .執行分組,得到虛擬表vt5。注意,分組之後,整個SQL的操作上下文就變成了分組列,而不再是表中的每一列,後續的一切操作都是圍繞所分的組作爲操作對象進行操作的。也就是說,不在分組列表中的列不能在後續步驟中使用。例如,使用"group by a"對a列分組,那麼後續的select列表中就不能使用b列,除非是對b列進行分組聚合運算。SQL Server、Oracle和MariaDB、Mysql最大的區別就在於此步,後兩者可以引用分組列以外的列。
  6. .對vt5執行集合操作cube或者rollup,得到虛擬表vt6。
  7. .對分組的最終結果vt6執行having篩選,得到虛擬表vt7。
  8. .根據給定的選擇列列表,將vt7中的選擇列插入到虛擬表vt8中。注意,選擇列是"同時性操作",在選擇列中不能使用列別名來引用列表中的其他列。例如 select col1+1 as a,a+1 as b from t1 是錯誤的,因爲"col1+1"和"a+1"之間沒有執行上的先後順序,所以它認爲"a+1"中的a列是不存在的。
  9. .對vt8進行窗口分組相關的計算,得到虛擬表vt9。
  10. .對vt9按照指定的列去除重複行,得到虛擬表vt10。這一步是將數據複製到內存中相同的臨時表結構中進行的,不過該臨時表多出了一個唯一性索引列用來做重複消除。
  11. .對vt10進行排序,排序後的表爲虛擬表vt11。
  12. .從vt11中根據top條件挑出其中滿足的行,得到虛擬表vt12。如果沒有應用order by,則記錄是無序的集合,top挑出的行可能是隨機的。也因此top一般要和order by字句一起使用。
  13. .將vt12從服務端返回給客戶端作爲最終查詢結果。

總之,sql優化要關注執行順序,優化項的執行順序再靠後的效果越差,性能提升越小。

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