MySql一條查詢語句的執(zhí)行流程究竟是怎么樣的
1.前言
一條sql語句到底在執(zhí)行時經(jīng)歷了什么?探究這個問題是學習mysql的重要步驟,面試時常被問到,也使得學習mysql時也有了知識框架的支撐,明白我們背的知識點到底用在哪里,筆者覺得這一點還是很重要的。
注:對一個知識點的總結不僅包含知識點本身,還包含對該知識點的聯(lián)想,這個聯(lián)想是在面試時可能被追問的,也可以自己主動說出來(我還知道。。。)加分的。
2.知識點
MySQL 執(zhí)行流程是怎樣的?
首先要知道的是,我們可以把mysql分成兩層,server層和數(shù)據(jù)庫引擎層,前者主要是對我們的查詢進行處理(主要包括 {連接器},{查詢緩存}、{解析器}、{預處理器、優(yōu)化器、執(zhí)行器} 等),后者是數(shù)據(jù)真正存儲的地方(從 MySQL 5.5 版本開始, InnoDB 成為了 MySQL 的默認存儲引擎)。
一條查詢的執(zhí)行流程如下:
第一步:通過連接器連接 MySQL 服務
mysql -h$ip -u$user -p
[連接器聯(lián)想1]: 連接經(jīng)過TCP 三次握手,斷開經(jīng)過四次揮手
[連接器聯(lián)想2]: 如果用戶密碼都沒有問題,連接器就會獲取該用戶的權限,然后保存起來,后續(xù)該用戶在此連接里的任何操作,都會基于連接開始時讀到的權限進行權限邏輯的判斷,意思是管理員修改已登錄用戶的權限需要等他重新登錄才生效
[連接器聯(lián)想3]: 如何查看 MySQL 服務被多少個客戶端連接了?
show processlist
[連接器聯(lián)想4]: 空閑連接會一直占用著嗎?MySQL 定義了空閑連接的最大空閑時長,由wait_timeout
參數(shù)控制的,默認值是 8 小時(28880秒),如果空閑連接超過了這個時間,連接器就會自動將它斷開。[連接器聯(lián)想5]: MySQL 的連接數(shù)有限制嗎?最大連接數(shù)由 max_connections 參數(shù)控制,超過這個值,系統(tǒng)就會拒絕接下來的連接請求,并報錯提示“Too many connections”。
[連接器聯(lián)想6]: 怎么解決長連接占用內(nèi)存的問題?MySQL 的連接也跟 HTTP 一樣,有短連接和長連接的概念,長連接的好處就是可以減少建立連接和斷開連接的過程,但是,使用長連接后可能會占用內(nèi)存增多,因為 MySQL 在執(zhí)行查詢過程中臨時使用內(nèi)存管理連接對象,這些連接對象資源只有在連接斷開時才會釋放。有兩種解決方式。第一種,定期斷開長連接。第二種,客戶端主動重置連接。
MySQL 5.7 版本實現(xiàn)了
mysql_reset_connection()
函數(shù)的接口來重置連接,達到釋放內(nèi)存的效果。這個過程不需要重連和重新做權限驗證,但是會將連接恢復到剛剛創(chuàng)建完時的狀態(tài)。[連接器聯(lián)想7]: 連接器的工作?與客戶端進行 TCP 三次握手建立連接;校驗客戶端的用戶名和密碼,如果用戶名或密碼不對,則會報錯;如果用戶名和密碼都對了,會讀取該用戶的權限,然后后面的權限邏輯判斷都基于此時讀取到的權限;
第二步:查詢緩存
連接器得工作完成后,客戶端就可以向 MySQL 服務發(fā)送 SQL 語句了,MySQL 服務收到 SQL 語句后,就會解析出 SQL 語句的第一個字段,看看是什么類型的語句。
如果 SQL 是查詢語句(select 語句),MySQL 就會先去查詢緩存( Query Cache )里查找緩存數(shù)據(jù)。
但是其實查詢緩存挺雞肋的。對于更新比較頻繁的表,查詢緩存的命中率很低的,因為只要一個表有更新操作,那么這個表的查詢緩存就會被清空。
所以,MySQL 8.0 版本直接將server層查詢緩存刪掉了。
第三步:解析SQL
在正式執(zhí)行 SQL 查詢語句之前, MySQL 會先對 SQL 語句做解析,這個工作交由「解析器」來完成。
解析器會做兩件事情:詞法分析、 語法分析。
[解釋器聯(lián)想1]: 詞法分析:MySQL 會根據(jù)你輸入的字符串識別出關鍵字出來,例如,SQL語句 select username from userinfo,在分析之后,會得到4個Token,其中有2個Keyword,分別為select和from.
[解釋器聯(lián)想2]: 語法分析:根據(jù)詞法分析的結果,語法解析器會根據(jù)語法規(guī)則,判斷你輸入的這個 SQL 語句是否滿足 MySQL 語法,如果沒問題就會構建出 SQL 語法樹,這樣方便后面模塊獲取 SQL 類型、表名、字段名、 where 條件等等。
[解釋器聯(lián)想3]: 解如果我們輸入的 SQL 語句語法不對,就會在解析器這個階段報錯。(釋器的主要作用)
[解釋器聯(lián)想4]: 解釋器只負責檢查語法和構建語法樹,但是不會去查表或者字段存不存在。
第四步:執(zhí)行 SQL
解析SQL無誤后,執(zhí)行SQL需要經(jīng)過三個步驟:預處理器、優(yōu)化器、執(zhí)行器。
預處理器
- 檢查 SQL 查詢語句中的表或者字段是否存在;
- 將
select *
中的*
符號,擴展為表上的所有列;
優(yōu)化器
優(yōu)化器主要負責將 SQL 查詢語句的執(zhí)行計劃確定下來,比如在表里面有多個索引的時候,優(yōu)化器會基于查詢成本的考慮,來決定選擇使用哪個索引。
[優(yōu)化器聯(lián)想1]: 要想知道優(yōu)化器選擇了哪個索引,我們可以在查詢語句最前面加個 explain
命令,這樣就會輸出這條 SQL 語句的執(zhí)行計劃。explain select * from product where id = 1
[優(yōu)化器聯(lián)想2]: 一般來講普通索引查詢效率高于主鍵索引,當索引覆蓋時會先考慮普通索引的B+樹上查詢,這就是執(zhí)行計劃,是優(yōu)化器決定的。
執(zhí)行器
確定了執(zhí)行計劃,接下來 MySQL 就真正開始執(zhí)行語句了,在執(zhí)行的過程中,執(zhí)行器就會和存儲引擎交互了,交互是以記錄為單位的。
- 主鍵索引查詢
select * from product where id = 1;
讓InnoDB引擎通過主鍵索引B+樹搜索id=1的記錄。 - 全表掃描
select * from product where name = 'iphone';
查詢條件沒有用到索引,觸發(fā)全表掃描,查詢每一條記錄判斷是否滿足條件。 - 索引下推 (MySQL 5.6 推出的查詢優(yōu)化策略)
[索引下推聯(lián)想1]: 索引下推能夠減少二級索引在查詢時的回表操作,提高查詢的效率,因為它將 Server 層部分負責的事情,交給存儲引擎層去處理了。select * from t_user where age > 20 and reward = 100000;
不使用索引下推(MySQL 5.6 之前的版本)時,定位到 age > 20 的一條記錄,獲取主鍵值,然后進行回表操作,將完整的記錄返回給 Server 層,Server 層再判斷該記錄的 reward 是否等于 100000。而使用索引下推后,判斷記錄的 reward 是否等于 100000 的工作交給了存儲引擎層:定位到 age > 20 的第一條記錄,存儲引擎定位到二級索引后,先不執(zhí)行回表操作,而是先判斷一下該索引中包含的列(reward列)的條件(reward 是否等于 100000)是否成立。如果條件不成立,則直接跳過該二級索引。如果成立,則執(zhí)行回表操作,將完成記錄返回給 Server 層。
MySQL 執(zhí)行流程是怎樣的?總結:
(總結只是簡單總結,也就是被問到時該說的,上面的知識點,是可能被追問時涉及的,或者自己說出來的加分項。)
- 連接器:建立連接,管理連接、校驗用戶身份;
- 查詢緩存:查詢語句如果命中查詢緩存則直接返回,否則繼續(xù)往下執(zhí)行。MySQL 8.0 已刪除該模塊;
- 解析 SQL,通過解析器對 SQL 查詢語句進行詞法分析、語法分析,然后構建語法樹,方便后續(xù)模塊讀取表名、字段、語句類型;
- 執(zhí)行 SQL:執(zhí)行 SQL 共有三個階段:
- 預處理階段:檢查表或字段是否存在;將
select *
中的*
符號擴展為表上的所有列。 - 優(yōu)化階段:基于查詢成本的考慮, 選擇查詢成本最小的執(zhí)行計劃;
- 執(zhí)行階段:根據(jù)執(zhí)行計劃執(zhí)行 SQL 查詢語句,從存儲引擎讀取記錄,返回給客戶端;
- 預處理階段:檢查表或字段是否存在;將
到此這篇關于MySql一條查詢語句的執(zhí)行流程究竟是怎么樣的文章就介紹到這了,更多相關MySql查詢語句執(zhí)行流程內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
MySQL常用命令與內(nèi)部組件及SQL優(yōu)化詳情
這篇文章主要介紹了MySQL常用命令與內(nèi)部組件及SQL優(yōu)化詳情,文章圍繞主題展開詳細的內(nèi)容介紹,具有一定的參考價值,需要的朋友可以參考一下2022-07-07利用MySQL主從配置實現(xiàn)讀寫分離減輕數(shù)據(jù)庫壓力
今天小編就為大家分享一篇關于利用MySQL主從配置實現(xiàn)讀寫分離減輕數(shù)據(jù)庫壓力,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧2019-03-03