1. 程式人生 > 資料庫 >MySQL執行一條查詢語句的內部執行過程

MySQL執行一條查詢語句的內部執行過程

MySQL執行一條查詢語句的內部執行過程

  1. 客戶端(執行程式)先通過聯結器連線到MySQL伺服器
  2. 聯結器通過資料庫許可權身份驗證後,先查詢資料庫快取是否存在(之前執行過相同條件的SQL查詢),如果有會直接返回快取中的資料。如果沒有則會進入分析器
  3. 進入分析器後會對查詢語句進行語法的分析,判斷該查詢語句SQL是否存在語法錯誤,如果存在查詢語法錯誤,會直接返回給客戶端錯誤,如果正確會進入優化器
  4. 優化器會對查詢語句進行優化處理:如:如果一條語句用到了多個索引會判斷哪個索引效能更好
  5. 最終會進入執行器,開始執行查詢語句直到查詢出滿足條件的所有資料,然後進行返回
詳細解讀

如下是MySQL基本架構圖

大體來說,MySQL可以分為Server層和儲存引擎兩部分

Server層: 包括聯結器、分析器、查詢快取、優化器、執行器

儲存引擎: 負責資料的儲存和提取。其架構模式是外掛式的,支援InnoDB、MyISAM、Memory等多種儲存模式。現如今最常用的儲存引擎是InnoDB,它從MySQL5.5.5開始成為預設儲存引擎。也就是說當我們不指定儲存引擎時預設使用的就是InnoDB,我們也可以在create table時通過engine=memory來指定儲存引擎

從圖中可以看出: 不同的儲存引擎共用同一個server層,也就是聯結器到執行器那一部分

聯結器

首先我們需要連線上資料庫,這時候接待我們的就是聯結器,聯結器主要負責的工作就是跟客戶端建立連線、獲取許可權、維持和管理連線。連線命令如下

mysql -h$ip -P$port -u$user -p
$ip: 伺服器IP
$port: MySQL埠號
$user: 使用者名稱
  • 如果使用者名稱或密碼不對,則會收到一個Access denied for user錯誤,然後客戶端程式結束執行
  • 如果使用者名稱密碼認證通過,聯結器則會去許可權表中查詢該使用者所擁有的許可權,這個連結裡的許可權邏輯判斷,全都依賴於此時讀到的許可權。

這就意味著,當一個使用者成功建立連線後,即使使用管理員賬戶對其許可權做了修改,也不會立即生效,只有重新建立連結後才會使用新的許可權設定

查詢快取

連結建立成功後,會先查詢快取:
MySQL拿到一個SQL語句之後會先到快取看看是否在此之前執行過這條語句,之前執行的語句會以key-value的形式直接快取在記憶體中。key是查詢語句,value是查詢結果。如果你的查詢能在快取中找到響應的key,則直接返回其對應的value給客戶端。

如果語句不再查詢快取中,就會繼續執行後面的階段。執行完成後,執行結果會被存入查詢快取中。你可以看到,如果命中快取,MySQL不需要執行後面的複雜操作,就可以執行返回結果,這個效率會很高

分析器

如果沒有命中快取,則真正開始執行語句了
分析器首先進行詞法分析。我們輸入的SQL是由多個字串組成的,MySQL需要識別出來裡面的字串分別是什麼。
詞法分析結束之後,需要對SQL進行語法分析。根據詞法分析的結果,語法分析器會根據語法規則來判斷我們輸入的這條SQL是否滿足MySQL的語法規則,如果我們的語法不對是話,我們會收到MySQL的錯誤提示You have an error in your SQL syntax

優化器

經過了分析器,MySQL知道我們要做什麼了,在它開始執行之前,還要先經過優化器的處理
優化器是在表裡面有多個索引的時候,決定使用那個索引,或者在一個語句有多表關聯的時候,決定各個表的連線順序。

select * from t1 join t2 using(ID)  where t1.c=10 and t2.d=20;

using()等價於on -> 當t1表於t2表關聯的欄位相同時 using(field) 和 t1.field = t2.field等價

  • 既可以先從表t1裡面取出c=10的ID值,再根據ID值去關聯到表t2,在判斷t2裡面的d值是否等於20
  • 也可以先從表t2裡面取出d=20的記錄的ID值關聯到t1,再判斷t1裡面的c值是否等於10

這兩種執行方法的邏輯和結果都是一樣的,但是執行效率會有所不同,優化器的作用就是決定選擇哪種方案

執行器

開始執行的時候,首先要確認我們是否有操作這個表的許可權,如果沒有許可權則會返回沒有許可權的錯誤

mysql> select * from T where ID=10;

ERROR 1142 (42000): SELECT command denied to user 'b'@'localhost' for table 'T'

如果有許可權,就開啟表極限執行,開啟表的時候執行器會根據表的引擎定義,去使用這個引擎提供的介面
比如在這個例子中的表T中的ID欄位時沒有索引的,那麼執行器的流程是這樣的

  • 條用InnoDB引擎介面去這個表的第一行,判斷ID是否為10,如果不是則跳過,如果時則將這行存在結果集中
  • 呼叫引擎介面取下一行,重複相同的邏輯判斷,直到取到這個表的最後一行
  • 執行器將上述便利過程的所有滿足條件的行組成的記錄集作為結果集返回給客戶端

面試題

MySQL提示不存在此列是執行到哪個節點報出的?

此錯誤是執行到分析器階段爆出的,因為MySQL會在分析器階段價差SQL語句的正確性

MySQL查詢快取的功能有何優缺點

MySQL查詢快取功能是在聯結器之後發生的,它的優點是效率高,如果已經有快取則會直接返回結果。查詢快取的缺點是失效太頻繁導致快取命中率比較低,任何更新表操作都會情況快取查詢,因此導致查詢效率非常容易失效

如何關閉MySQL的查詢快取功能

MySQL查詢快取預設是開啟的,配置querycachetype引數為DEMAND(按需使用)關閉快取。MySQL8.0之後直接刪除了查詢快取的功能
在這裡插入圖片描述