一文讀懂MySQL查詢語句的執行過程

須要從數據庫檢索某些符合要求的數據,咱們很容易寫出 Select A B C FROM T WHERE ID = XX  這樣的SQL,那麼當咱們向數據庫發送這樣一個請求時,數據庫到底作了什麼?java

咱們今天以MYSQL爲例,揭示一下MySQL數據庫的查詢過程,並讓你們對數據庫裏的一些零件有所瞭解。mysql

MYSQL架構

mysql架構程序員

MySQL 主要能夠分爲 Server 層和存儲引擎層。算法

Server層 包括鏈接器、查詢緩存、分析器、優化器、執行器等,全部跨存儲引擎的功能都在這一層實現,好比存儲過程、觸發器、視圖、函數等,還有個通用的日誌模塊binlog日誌模塊;sql

存儲引擎層 負責數據的存儲和提取。其架構模式是插件式的,支持 InnoDB、MyISAM、Memory 等多個存儲引擎。如今最經常使用的存儲引擎是 InnoDB(支持事務),它從 MySQL5.5.5 版本開始成爲默認存儲引擎。數據庫

鏈接器

鏈接器主要負責用戶登陸數據庫,進行用戶的身份認證,包括校驗帳戶密碼,權限等操做。緩存

若是用戶密碼不對,你就會收到一個"Access denied for user"的錯誤,而後客戶端程序結束執行。微信

若是用戶帳戶密碼已經過,鏈接器會到權限表中查詢該用戶的全部權限,以後在這個鏈接裏的權限邏輯判斷都是會依賴此時讀取到的權限數據,也就是說,後續只要這個鏈接不斷開,即時管理員修改了該用戶的權限,該用戶也是不受影響的。數據結構

查詢緩存( Query cache)

客戶端與服務端創建鏈接後,MySQL 在執行查詢語句時會先查詢緩存,校驗這條SQL是否是在以前執行過。以前執行過的語句及其結果會以 key-value 對的形式,被直接緩存在內存中。key 是查詢的語句,value 是查詢的結果。若是你的查詢可以直接在這個緩存中找到 key,那麼這個value 就會被直接返回給客戶端。若是沒有命中,則須要執行後續的操做,完成後也會把結果緩存起來,方便下一次調用。架構

看到這裏你們會不會眼前一亮,會不會有這個功能很好要好好利用的衝動。

其實這裏並不建議使用查詢緩存,查詢緩存的失效很是頻繁,只要有對一個表的更新,這個表上全部的查詢緩存都會被清空。所以極可能你費勁地把結果存起來,還沒使用就被一個更新全清空了。對於更新壓力大的數據庫來講,查詢緩存的命中率會很是低。除非是那種很長時間不會更新的表,好比系統配置表,可是這種系統配置咱們放在配置平臺很差嗎?

在MYSQL8.0中已經刪除了查詢緩存這個功能,官方也是認爲該功能在實際的應用場景比較少,因此乾脆直接刪掉了。

分析器

Mysql沒有命中查詢緩存,那麼就會進入分析器,分析器主要是用來分析SQL語句是來幹嗎的。分析器主要分爲如下兩步:

  • 詞法分析 :一條SQL語句有多個字符串組成,首先要提取關鍵字,好比select,提出查詢的表,提出字段名,提出查詢條件等等。

  • 語法分析:根據詞法分析的結果,語法分析主要就是判斷你輸入的SQL語句是否正確,是否符合MYSQL語法,若是你的語句不對,就會收到「You have an error in your SQL syntax」的錯誤提醒。

詞法分析程序將整個查詢語句分解成各種標誌,語法分析根據定義的系統語言將「各種標誌」轉爲對MySQL有意義的組合。最後系統生成一個語法樹(AST),語法樹即是優化器依賴的數據結構。

優化器

通過了分析器,MySQL 就知道你要作什麼了。在開始執行以前,還要先通過優化器的處理。

爲何須要優化器?

  • 優化器中包含了許多 複雜的優化技術,這些優化技術每每比最好的程序員掌握的還要多。系統的自動優化至關於使得全部人都擁有這些優化技術。

  • 優化器能夠從數據字典中獲取許多 統計信息,例如表中的行數、表中的每一個列的分佈狀況等。優化器優化器能夠考慮百種不一樣的執行計劃,而程序員通常只能考慮有限的幾種可能;

  • 能夠根據這些信息選擇 有效的執行計劃,而用戶程序則難以得到這些信息;

總之優化器是對語法分析樹的形態進行修改,把語法分析樹變爲查詢樹,肯定執行方案。

執行器

MySQL 經過分析器知道了你要作什麼,經過優化器知道了該怎麼作,因而就進入了執行器階段,開始執行語句。

開始執行的時候,要先校驗改用戶是否有執行查詢的權限,若是沒有,就會返回沒有權限的錯誤。若是有權限,就會去調用引擎的接口,返回接口執行的結果。

語句分析

咱們如下面一條真實SQL查詢語句來進行分析下MYSQL查詢的執行過程

select id,name,sex,phoone from user t where t.age='26' and t.account='javadaily'

  • 首先客戶端須要鏈接上數據庫,若是帳號密碼錯誤直接返回錯誤信息,若是正確則進入下一步。
     

  • 在MYSQL8.0以前會先去查詢緩存中,以這條SQL語句做爲key在內存中查詢是否有結果,若是有則先判斷是否有權限,有權限則返回客戶端,不然報錯;若是沒有從查詢緩存命中則進入下一步
     

  • 經過分析器進行詞法分析,提取sql語句的關鍵元素,好比提取上面這個語句是查詢select,提取須要查詢的表名爲 user,須要查詢的列爲 id,name,sex,phoone,查詢條件是 age=26account=javadailly。而後判斷這個sql語句是否有語法錯誤,好比關鍵詞是否正確等等,若是檢查沒問題就執行下一步。
     

  • 上面的SQL有兩種執行方案,優化器根據本身的優化算法選擇執行效率最高的a方案(統計信息不許可能致使優化器選擇錯誤的執行方案),肯定了優化方案後就開始執行。

a. 先查詢 account=javadaily 的用戶,而後判斷 age 是否等於26
b. 先找出
age=26 的用戶,再查詢 account=javadaily 的用戶
  • 進行權限校驗,若是有查詢權限則調用數據庫引擎接口返回執行結果;不然報錯。

 

 

以上,但願對你有所幫助!

這裏爲你們準備了一份小小的禮物,關注公衆號,輸入以下代碼,便可得到百度網盤地址,無套路領取!

001:《程序員必讀書籍》
002:《從無到有搭建中小型互聯網公司後臺服務架構與運維架構》
003:《互聯網企業高併發解決方案》
004:《互聯網架構教學視頻》
006:《SpringBoot實現點餐系統》
007:《SpringSecurity實戰視頻》
008:《Hadoop實戰教學視頻》
009:《騰訊2019Techo開發者大會PPT》

010: 微信交流羣

 

 

 

 

 

本文分享自微信公衆號 - JAVA日知錄(javadaily)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。

相關文章
相關標籤/搜索