如果想深入學習 MySQL ,那麼應該從宏觀的架構上面著手,這篇我們學習 MySQL 查詢語句執行的流程,希望對大家有幫助!
本篇文章MySQL 版本為8.0.18
解析器的作用是針對客戶端傳來的SQL 語句進行以下工作:
#解析器主要是檢查語法詞法方面,但是如果語法詞法都正確,但是表、字段是不存在的,那麼這段SQL 語句也是無法正確執行的。
所以預處理器的作用是:語意解析,判斷解析樹的語意是否正確,表、字段這些是否存在,預處理後會得到一顆新的解析樹。
查詢最佳化器結構
#在MySQL 中一條SQL 語句的執行方式有多種,雖然最終都會得到相同的結果,但是存在開銷上的差異,具體選擇哪一種執行方式是由查詢優化器來決定的。比方說:
查詢最佳化器是基於開銷(cost)的最佳化器,它的工作原理是根據解析樹產生的多種執行計劃,會評估各種執行方式所需的開銷(cost),最終會得到一個開銷最小的執行計劃作為最終方案。
但是這個開銷最小的執行方式不一定是最優的執行方式,例如本該使用索引,卻進行了全表掃描等。雖然查詢優化器中有《優化》兩個字,但這個優化並不是萬能的,很多時候更需要考慮 SQL 語句寫得是否合理。
邏輯查詢最佳化主要負責進行一些關係代數對SQL 語句進行最佳化,使SQL 語句執行效率更高
邏輯查詢優化我們可以使用幾個案例來簡單理解
子查詢合併
#合併前
SELECT * FROM t1 WHERE a1<10 AND ( EXISTS(SELECT a2 FROM t2 WHERE t2.a2<5 AND t2.b2=1) OR EXISTS(SELECT a2 FROM t2 WHERE t2.a2<5 AND t2.b2=2) );
合併後
SELECT * FROM t1 WHERE a1<10 AND ( EXISTS(SELECT a2 FROM t2 WHERE t2.a2<5 AND (t2.b2=1 OR t2.b2=2) );
把多個子查詢透過合併查詢條件合併查詢,把多次連線運算減少為單次表掃描和單次連線
等價謂詞重寫
#像我們熟悉的like 模糊查詢,% 寫在條件後面才會進行索引範圍查詢,其實這是查詢優化器的功勞
假設使用的條件都是有建立索引的,重寫前
SELECT * FROM USERINFO WHERE name LIKE 'Abc%';
重寫後
SELECT * FROM USERINFO WHERE name >= 'Abc' AND name < 'Abd';
這就是為什麼能進行索引範圍查詢的答案
條件簡化
條件簡化也是利用一些等式、代數關係來實現簡化
((a AND b) AND (c AND d))
簡化為a AND b AND c AND d
col1 = col2 AND col2 = 3
簡化為col1 = 3 AND col2 = 3
col1 = 1 2
簡化為col1 = 3
物理查詢最佳化主要做的工作是根據SQL語句分別對多種執行計畫進行開銷的評估
物理查詢最佳化主要解決以下幾個問題:
單表掃描中採用哪一種方式是開銷最小的(掃描索引回表or 全表掃描)
存在表連接的時候使用哪種連接方式是開銷最小的
代價評估公式 | |
---|---|
N_page * a_page_IO_time N_tuple * a_tuple_CPU_time | |
C_index N_page_index * a_page_IO_time |
以上是MySQL學習之聊查詢語句執行流程的詳細內容。更多資訊請關注PHP中文網其他相關文章!