MySQL解析過程和執行過程

MySQL解析過程和執行過程

MySQL解析過程

MySQL解析過程

  • 首先客戶端會發送一條查詢到服務器;
  • 服務器先檢查查詢緩存【在8.0版本中被取消】,如果命中了緩存則立刻返回緩存中的結果,否則進入下一階段
  • SQL語句進入解析器並生成語法樹,對SQL語句進行檢查【主要檢查語法格式的正確性】,若檢查不通過則返回You hava an error in your SQL syntax的錯誤
  • SQL語句進入預處理器,主要用來檢查表,表的列是否存在,若不存在則返回Unknown column xxx in 'where clause'的錯誤
  • 之後對SQL語句進行權限檢查【在預處理器中進行】
  • SQL語句進入優化器,對SQL語句進行優化【例如對連接查詢的優化】。優化之後優化器根據SQL生成執行計劃並交給執行器
  • 執行器通過執行計劃的指令調用底層存儲引擎來逐步執行【其中存儲引擎實現了一系列抽象存儲引擎的接口】。執行完畢之後將結果返回到客戶端,若執行的SQL是SELECT類型的,則還會把結果存儲到查詢緩存中。

執行SQL的具體過程:

  1. MySQL客戶端和服務器進行通訊:
    MySQL客戶端和服務器之間的通信是“半雙工”的,即發送和接收不能同時發生,這種協議讓MySQL通信簡單快速,但是一個明顯的限制就是流量限制,一端開始發送消息那麼另一端需要接收完畢消息纔可發送。
  2. 查詢狀態:SHOW [FULL] PROCESSLIST
    查詢生命週期中狀態多變,主要的狀態:
    a) sleep //線程正在等待客戶端發送新的請求
    b) query //線程正在執行查詢或正在將結果發送給客戶端
    c) locked //在mysql服務器層,該線程正在等待表鎖
    d) sending data //線程可能在多個狀態間傳送數據,或者在生成結果集,或者在向客戶端返回數據
    e) …
  3. 查詢緩存
    查詢緩存本質上是一張Hash表,它將執行過的語句及其結果會以key-value對的形式被直接緩存在內存中【key是一個通過查詢SQL、當前要查詢的數據庫、客戶端協議版本等生成的一個哈希值,value是查詢結果】
    在解析一個查詢語句之前,如果查詢緩存是打開的,那麼MySQL會優先檢查這個查詢是否會命中查詢緩存中的數據。
    8.0版本取消掉查詢緩存的原因:
    1. 只要對錶進行更新,那麼這個表上的查詢緩存就都會被清空
    2. SQL任何字符上的不同【空格,註釋等】都會導致緩存不命中
  4. 解析器:
    將請求的SQL生成一顆語法樹,例如:
    SELECT emp_id FROM employee
    先進行詞法分析:從左到右將字符依次輸入,然後識別單詞,會得到4個token:
關鍵字 非關鍵字 關鍵字 非關鍵字
SELECT emp_id FROM employee

之後進行語法分析:判斷輸入的SQL語句是否滿足MySQL語法,然後生成語法樹:
語法樹
5. 預處理器
根據MySQL的規則進一步檢查語法樹【主要是對錶是否存在,列是否存在,權限是否足夠等進行檢查】
6. 優化器
優化器的作用是找到最好的執行計劃
執行計劃;:MySQL不會生成查詢字節碼來執行查詢,MySQL生成查詢的一顆指令樹,然後通過存儲引擎執行完成這顆指令樹並返回結果。
7. 查詢執行引擎
這裏的執行計劃是一個數據結構,而不是和很多其他的關係型數據庫那樣對應的字節碼。
在根據執行計劃逐步執行的過程中有大量的操作需要通過調用存儲引擎實現的接口方法。
8. 返回結果給客戶端
查詢執行的最後一個階段是將結果返回給客戶端。即使查詢不需要返回結果給客戶端,mysql仍然會返回這個查詢的一些信息,如該查詢影響到的行數。如果查詢可以被緩存,那麼mysql在這個階段也會將結果放到查詢緩存中。
mysql將結果集返回客戶端是一個增量、逐步返回的過程。這樣有兩個好處:服務器端無須存儲太多的結果,也就不會因爲返回太多結果而消耗太多的內存;這樣處理也讓msyql客戶端第一時間獲得返回的結果。

MySQL執行過程

SQL是一套標準,全程結構化查詢語言,是用來完成和數據庫之間通信的編程語言,SQL語言是腳本語言,直接運行在數據庫上,同時SQL語句與數據在數據庫上的存儲方式無關,只是不同的數據庫對於同一條語句的底層實現不同罷了,但結果相同。
設有如下語句:
SELECT name,COUNT(name) AS num FROM student WHERE grade<60 GROUP BY 'name' HAVING num>=2 ORDER BY num DESC,name ASC LIMIT 0,2【查詢出掛科數多餘兩門(含2門)的前兩名學生的姓名,若掛科數一樣則按照姓名升序排序】

  1. 一條查詢的SQL語句先執行的是FROM student負責把數據庫的標文件加載到內存中去
  2. WHERE grade<60
  3. GROUP BY name
  4. SELECT的執行讀取規則分爲sql語句中有無GROUP BY兩種情況:
    1)當沒有GROUP BY的時候,SELECT會根據後面的字段名稱對內存中的一張臨時表整列讀取
    2)當查詢SQL中有GROUP BY時,會對內存中的若干臨時表分別執行SELECT,而且只取各臨時表中的第一條記錄,然後再形成新的臨時表。這就決定了查詢sql使用GROUP BY的場景下,SELECT後面跟的一般是參與分組的字段和聚合函數,否則查詢出的數據要視情況而定。另外聚合函數中的字段可以是表中的任意字段,需要注意的是聚合函數會自動忽略空值。
  5. HAVING num>=2對4形成的臨時表中的數據再次進行過濾
    與WHERE語句不同的是HAVING 用在GROUP BY之後, WHERE是對FROM student從數據庫表文件加載到內存中的原生數據過濾,而HAVING 是對SELECT 語句執行之後的臨時表中的數據過濾。 但HAVING的後使用的字段只能是SELECT 後的字段,SELECT後沒有的字段HAVING之後不能使用
  6. ORDER BY num DESC
  7. LIMIT 0,2
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章