Select * from user的千層套路

Select * from user的千層套路

​ 作爲一個java程序員,我們會經常和sql打交道,但是有事情我們確實不知道sql語句背後的處理邏輯比如下面這個sql

select * from user where id='1';

​ 對於這麼一條操作來說mysql服務器做了哪些處理呢?下面我們將說一下關於mysql數據庫中對sql語句的處理邏輯

MySql的基本架構

​ 要想要了解sql語句的內部處理邏輯,我們需要先學習Mysql的基本架構圖,這樣才能更好的把握Mysql數據庫

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-62fx4rBp-1592558179311)(https://raw.githubusercontent.com/iszhonghu/Picture-bed/master/img/20200619140642.png)]

​ 從圖中我們可以清楚的看到Mysql的架構和各個模塊以及SQL語言的執行過程。

​ Mysql數據庫整體可以分爲Server層和存儲引擎層兩部分。其中Server層是共有的,而存儲引擎層是可以以插件的形式進行擴展

​ 一條Sql語句大概會經歷鏈接管理、解析與優化、最後到存儲引擎,這三個模塊

連接管理

​ 連接管理是SQL語句執行過程中的第一關,控制着客戶端和Server服務端的交互,連接管理主要工作是客戶端的身份認證和連接線程的管理、

​ 每個客戶端與Server建立連接時,服務器會創建一個線程來與客戶端交互,交互的第一項內容就是驗證客戶端的身份,認證憑證是基於客戶端發起連接請求時攜帶的主機信息、用戶名、密碼。

​ 如果認證失敗,則結束連接任務,並且返回Access denied for user的錯誤

​ 如果認證成功,還會到權限表中查詢該用戶的權限,在此次連接下,後續的權限判斷都是基於此時讀取的權限爲依據。

  • 主要是負責客戶端與服務端進行連接,當然在連接線程上,連接管理也做了優化,並不是每個客戶端執行完任務之後,就把該線程銷燬,連接管理會把這些線程緩存起來,等待新的連接,這也就不會頻繁的創建和銷燬線程,從而節約了開銷。

解析與優化

​ 完成連接管理之後,SQL 語句執行的第二步就是解析和優化,SQL 語句查詢的所有操作都在這裏了。

查詢緩存

​ MySQL 服務器拿到查詢請求後,會先到查詢緩存看看,之前是不是執行過這條語句。之前執行過的語句及其結果可能會以 key-value 對的形式,被直接緩存在內存中。key 是查詢的語句,value 是查詢的結果。

​ 但是實際使用中會有很多問題:

  • 命中率低下:只要有稍微的不同就不會命中
  • 緩存數據發送了變化,導致取到錯誤數據
  • 一旦表中數據或結構改變了緩存也會刪除

​ 所以緩存對 MySQL 數據庫來說弊大於利,所以在 MySQL 8.0 版本直接將查詢緩存的整塊功能刪掉了

語法解析和預處理

​ 如果查詢緩存沒有命中,接下來就需要進入正式的查詢階段了。因爲客戶端程序發送過來的請求只是一段文本而已,所以 MySQL 服務器程序首先要對這段文本做語法解析。

​ 首先通過關鍵字將 SQL 語句進行解析,並且生成一個“解析樹”。MySQL 解析器將使用 MySQL 語法規則驗證和解析查詢,例如,關鍵字是否使用正確、關鍵字的順序是否正確或者引號是否前後匹配等。

​ 預處理是根據一些 MySQL 規則進一步檢查解析樹是否合法,例如數據表和數據列是否存在,還會解析名字和別名,看看他們是否有歧義等。

查詢優化

​ MySQL 的優化程序會對我們的語句做一些優化,如外連接轉換爲內連接、表達式簡化、子查詢轉爲連接等等。優化的結果就是生成一個執行計劃,這個執行計劃表明了應該使用哪些索引進行查詢,表之間的連接順序是啥樣的。

執行器

​ 執行器會執行查詢優化後的執行計劃,通過與存儲引擎交互,完成數據的查詢操作,返回最終的數據結果。

​ 開始執行的時候,要先判斷一下你對這個表 T 有沒有執行查詢的權限,如果沒有,就會返回沒有權限的錯誤

​ 如果有權限,就打開表繼續執行。打開表的時候,執行器就會根據表的引擎定義,去使用這個引擎提供的接口。

比如我們這個例子中的表 user 中,假設 ID 字段沒有索引,那麼執行器的執行流程是這樣的:

1、調用 InnoDB 引擎接口取這個表的第一行,判斷 ID 值是不是 10,如果不是則跳過,如果是則將這行存在結果集中;

2、調用引擎接口取“下一行”,重複相同的判斷邏輯,直到取到這個表的最後一行。

3、執行器將上述遍歷過程中所有滿足條件的行組成的記錄集作爲結果集返回給客戶端。

到這裏,執行 SQL 語句就執行完了,其實這內部還是非常複雜的。

存儲引擎

​ 到上面爲止,SQL 語句就執行完了,但是與真實數據打交道的是存儲引擎,存儲引擎是 MySQL服務器對數據的存儲和提取操作的封裝模塊。我們知道表是由一行一行的記錄組成的,但這只是一個邏輯上的概念,物理上如何表示記錄,怎麼從表中讀取數據,怎麼把數據寫入具體的物理存儲器上,這都是存儲引擎負責的事情。

​ 爲了實現不同的功能,MySQL提供了各式各樣的存儲引擎,不同存儲引擎管理的表具體的存儲結構可能不同,採用的存取算法也可能不同。比如,MySQL5.7 之後默認的 InnoDB 存儲引擎。

SQL提供了各式各樣的存儲引擎,不同存儲引擎管理的表具體的存儲結構可能不同,採用的存取算法也可能不同。比如,MySQL5.7 之後默認的 InnoDB 存儲引擎。

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