mysql 查询执行过程_深入浅出Mysql(一)——sql查询执行过程
一、sql查詢執行過程概括
下面給出的mysql基本架構示意圖,從中你可以清楚的mysql的各個模塊和執行過程。
大體來說可以分為兩部分Server層和儲存引擎層。Server層包括連接器、查詢緩存、分析器、優化器、執行器等,覆蓋了mysql的大部分核心服務功能,以及所有的內置函數(如日期、時間、數字和加密函數等)
儲存引擎層負責數據的儲存和提取。其架構模式是插件式的,支持Innodb、MyISAM等多個儲存引擎。現在最常用的儲存引擎是Innodb,從Mysql5.5.5開始為其默認引擎。
從圖中不難看出所有的引擎都是公用server層。不知道每個組件干什么用?先對圖中的組件有一個大概印象,接下來將介紹server層的一些組件的作用。
二、連接器
我們會先要連接到數據庫,這時候接待你的就是連接器,連接器負責客戶端和數據庫建立連接、獲取權限、維持和管理連接。客戶端連接的命令一般會這樣寫:
mysql -h$ip -u$name -p$pwd
在完成經典的tcp三次握手之后建立連接、一旦建立連接和認證通過,連接器會從權限表中查詢你擁有的權限,此連接的權限都會依賴此權限(修改權限后也不會改變,除非重新啟動)
連接完成后,如果沒有動作,則會處于空閑狀態,可以用show processlist, 下面是命令的返回結果,其中Sleep表示有一個空閑連接
當客戶端太長時間沒有動靜,連接器就會自動斷開。這個時間參數可以根據wait_timeout控制,默認是8小時。
在數據庫里面,長連接是指連接成功之后,客戶端有請求,則會一直用這個連接。短鏈接是指每一次執行很少的查詢后就會斷開連接,之后查詢則需要重新建立連接。
建立連接的過程比較復雜,占用的時間也比較長 ,所以筆者建議最好使用長連接。
但是長連接也不是十全十美,當你建立長連接之后,你可能會發現mysql占用的內存漲的非常快,因為mysql在執行的過程中所產生的臨時對象是管理在該連接對象里面的。這些資源在連接斷開的時候才會釋放,當長連接持續過久,可能內存占用過大,就會被系統強行殺掉,從表面上看是mysql異常重啟了。
所以我們一般會怎么解決這種問題呢。我們一般會考慮下面兩種方案:定期斷開長連接。在使用一段時間后或者執行一次占內存較大的查詢后會斷開連接,之后查詢再連接。
如果是mysql5.7后的版本,可以通過執行mysql_reset_connection來初始化資源,該過程不會去重新連接和驗證權限
三、查詢緩存
當建立連接完成后,就可以執行查詢語句了,此時會執行查詢邏輯的第二步:查詢緩存
可以參考上圖,mysql拿到一個查詢后,會先到查詢緩存去看看之前是否執行過此條語句。之前執行的結果會以key-value的形式被直接存在內存里面。如果語句不在緩存中,則會繼續執行下面的步驟,最后將結果緩存到查詢緩存中。
但是一般情況下都不會建議用查詢緩存,因為一旦對一張表進行更新插入等更改表的操作,關于這個表的緩存就是被清空。由此導致查詢緩存的命中率就會很低。所以除非你有一張靜態表,很長時間才會更新一次,否則建議不用查詢緩存。
mysql中可以把query_cache_type設置成DEMAND,此時默認的sql就不會執行緩存,需要緩存時需要顯示指定:
select SQL_CACHE * from T where ID=10
值得注意的是,再mysql8.0版本中查詢緩存的功能被完全刪掉了。
四、分析器
如果沒有命中緩存,就開始真正的執行語句了。首先,mysql需要知道你要做什么,所以需要對sql進行解析。
分析器首先會對sql進行詞法分析,mysql需要識別sql語句的字符串分別是什么,代表什么。詞法分析會把例如“select”這些關鍵字識別出來,也會把字符串“T”識別成表名“T”。
做完詞法分析后,就要做語法分析。語法分析會根據語法規則判斷輸入的sql語句是否滿足mysql語法。比如你的“select”少了一個s,收到“You have an error in your SQL syntax"的錯誤提醒。關于分析器的詞法分析和語法分析具體過程和實現原理可以單獨寫一篇文章,在之后的文章中會給出。
五、優化器
在分析器之后,mysql就知道你要做什么了。開始執行之前,還需要優化器處理。
優化器的主要作用是在表中有多個索引的時候,決定用哪個索引;或者在一個語句有多表關聯(join)的時候,決定各表的連接順序。以下面的sql語句為例子:
select * from t1 join t2 on ID where t1.c=10 and t2.d=20;
既可以從t1中取出c等于10的記錄,然后再關聯到t2,然后再判斷t2表中d是否等于20的行;也可以從t2中取出d等于20的記錄,然后再關聯到t1,然后再判斷t1表中的c是否等于10 。優化器會更具上兩種哪個的執行效率更高而決定用哪種方案。
對于優化器一些具體的實現方案,比如怎么選擇索引等,后面會再文章中解釋。
六、執行器
優化器完成以后,就要到執行器的階段了。執行器開始執行的時候會判斷你對這個表是否有查詢權限(如果在之前的查詢緩存返回結果,會在返回結果之前也做一次權限驗證)。下面是沒有權限認證的一個示例:
mysql> select * from T where ID=10;
ERROR 1142 (42000): SELECT command denied to user 'b'@'localhost' for table 'T'
當驗證權限之后,就會打開表繼續執行,執行器會根據表的引擎定義,去使用這個引擎提供的接口。
還是以上面例子分析,假如ID字段中沒有索引,則執行的流程是這樣的:調用InnoDB引擎接口取這個表的第一行,判斷ID值是否為10,如果不是則跳過,如果是則將 這行存在結果集中。
調用引擎接口,取下一行,判斷相同的邏輯,直到取到最后一行。
執行器將上面所有的結果集返回客戶端。
對于有索引的的表,執行邏輯也差不多。第一次就會執行”滿足條件的第一行“接口,之后循環取“滿足條件的下一行”這個接口。
在慢查詢日志中,你會看見一個rows_examined的字段,該字段會表示語句執行過程中掃描了多少行。這個值是在執行器在掃描每一行的時候累加的。在有些場景下,執行器調用一次,在引擎內部則掃描了多行,因此引擎掃描行數rows_examined 并不是完全相同的。之后準備寫一篇文章來講存儲引擎的內部機制,里面會有詳細的說明。
七、總結
這篇文章介紹了mysql的邏輯架構,希望可以幫助大家對mysql的完整執行流程的各個階段有一個初步的印象。對于每個階段細節問題,將會在之后的篇幅中展開。
總結
以上是生活随笔為你收集整理的mysql 查询执行过程_深入浅出Mysql(一)——sql查询执行过程的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 百度确认其类 ChatGPT 产品名为“
- 下一篇: kudu导出为mysql格式_怎么实现k