一條SQL查詢語句是如何執行的?-筆記

MySQL基本架構示意圖如下,從圖中我們可以清楚地看到SQL語句在MySQL的各個功能模塊中的執行過程
MySQL可分爲Server層存儲引擎層兩部分。

Server層包括連接器、查詢緩存、分析器、優化器、執行器等,涵蓋MySQL的大多數核心服務器功能以及所有的內置函數(日期、時間、數學和加密函數等),所有跨存儲引擎的功能都在這一層實現,比如存儲過程、觸發器、視圖等。

存儲引擎負責數據的存儲提取。其架構模式是插件式的,支持InnoDB,它從MySQL5.5.5版本開始成爲了默認存儲引擎。
圖中可以看到不同存儲引擎共用一個Server層。

連接器

首先,我們連接到這個數據庫上,這時接待你的就是連接器,連接器負責與客戶端建立連接、獲取權限、維持和管理連接。連接命令如下:

mysql -h$ip -P$port -u$user -p

密碼可直接跟在-p後面寫在命令行中,但是這樣可能會導致你的密碼泄露。因此輸完命令後我們最好在交互對話裏面輸入密碼

連接命令中的mysql是客戶端工具,用來跟服務器建立連接,在完成經典的TCP握手後,連接器就要開始認證你的身份。用戶名和密碼認證通過後,連接器會到權限表裏面查出你擁有的權限。之後這個連接裏的權限判斷邏輯都將依賴於此時讀到的權限。這意味着,用戶連接成功後,即使管理員賬號對這個用戶的權限做了修改,也不會影響已存在連接的權限,只有新建的連接纔會使用新的權限設置。鏈接完成後若沒有後續的動作,這個連接就處於空閒狀態,你可以在show processlist命令中看到它。若客戶端太長時間沒有動靜,連接器就會自動將它斷開。這個時間由參數wait_timeout控制,默認值8h

數據庫中長連接是指連接成功後,如果客戶端持續有請求,則一直使用一個連接。短連接則是指每次執行完很少的幾次查詢就斷開連接,下次查詢新建。使用中儘量減少建立連接的動作,即多使用長連接。

但全使用長連接會使MySQL佔用內存漲的特別快,若長期下來可能導致內存佔用太大,被系統強行殺掉(OOM),從現象來看就是MySQL重啓。如何解決這個問題?

  • 定期斷開長連接
  • 若使用的MySQL5.7以上新版本,可在每次執行一個比較大的操作後通過執行mysql_reset_connection來重新初始化連接資源。

查詢緩存

MySQL拿到一個查詢請求後會先到查詢緩存看看,之前是不是執行過這條語句。之前執行的語句及其結果會以key-value對的形式被直接緩存在內存中。若查詢能在緩存中找到key,那麼這個value會被直接返回給客戶端。若不在查詢緩存中,會繼續後面的執行階段,執行完畢將結果存入查詢緩存中。
若查詢命中緩存,MySQL不需要執行後面的複雜操作就可以直接返回結果,這個效率會很高。

但查詢緩存弊大於利!!

只要對錶更新,這個表上所有的查詢緩存都會被清空。若數據庫經常更新,那麼查詢緩存的命中率會非常低。若是一張很長時間纔會更新一次的靜態表才適合使用查詢緩存。

將參數query_cache_type設置成DEMAND,這樣對於默認的SQL語句都不使用查詢緩存,需要查詢緩存的語句,使用SQL_CACHE顯示指定,例如:
mysql> select SQL_CACHE * from T where ID=10;

注意!!!MySQL8.0版本中直接將查詢緩存刪了,即徹底沒有這個功能了。

分析器

這裏開始真正執行語句了。MySQL對語句做解析。分析器先做“詞法分析”,再做“語法分析”。這個階段就可以分析出表中是否存在對應的字段,比如 select * from T where k=1,k列不存在就會報錯。

優化器

當表中有多個索引的時候,決定使用哪個索引或在一個語句中有多表關聯的時候,決定各個表的連接順序,不同的順序會有不同的執行效率。

執行器

開始執行時要先判斷你對這個表有沒有執行查詢的權限,有權限就繼續打開表執行。打開表的時候,執行器就會根據表的引擎定義,去使用這個引擎提供的接口。

執行順序是“第一次調用取滿足條件的第一行這個接口”然後“循環取滿足條件的下一行這個接口”,這些接口都是引擎中已經定義好的。數據庫慢查詢日誌中會看到一個rows_examined字段,這個值是在執行器每次調用引擎獲取數據行的時候累加的,但某些情況下執行器調用一次,在引擎內部掃描多行,因此引擎掃描函數與rows_examined不完全相同

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