MySQL提高筆記(1):MySQL邏輯架構

深刻學習MySQL,從概覽MySQL邏輯架構開始。mysql

首先來看一下MySQL的邏輯架構圖:sql

MySQL邏輯架構

MySQL邏輯架構大概能夠分爲三層:數據庫

  • 客戶端:最上層的服務並非MySQL所獨有的,大多數基於網絡的客戶端/服務器的工具或者服務都有相似的架構。好比鏈接處理、受權認證、安全等等。
  • Server層:大多數MySQL的核心服務功能都在這一層,包括查詢解析、分析、優化、緩存以及全部的內置函數(例如,日期、時間、數學和加密函數),全部跨存儲引擎的功能都在這一層實現:存儲過程、觸發器、視圖等。
  • 存儲引擎層:第三層包含了存儲引擎。存儲引擎負責MySQL中數據的存儲和提取。Server層經過API與存儲引擎進行通訊。這些接口屏蔽了不一樣存儲引擎之間的差別,使得這些差別對上層的查詢過程透明。

值得一提的是在MySQL8.0中取消了查詢緩存,大概的理由是查詢緩存存在嚴重的可伸縮性問題,而且很容易成爲嚴重的瓶頸緩存,將緩存移動到客戶端能收穫更好的性能。緩存

MySQL查詢緩存

經過一條查詢語句的執行過程,來了解一些關鍵的部件:安全

mysql> select * from T where ID=10;

一、鏈接器

首先,須要鏈接數據庫。服務器

當客戶端(應用)鏈接到MySQL服務器時,服務器須要對其進行認證。認證基於用戶名、原始主機信息和密碼。網絡

鏈接命令:架構

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

除了基本認證以外,鏈接器還會進行一些線程的處理。函數

每一個客戶端鏈接都會在服務器進程中擁有一個線程,這個鏈接的查詢只會在這個單獨的線程中執行,該線程只能輪流在某個CPU核心或者CPU中運行。服務器會負責緩存線程,所以不須要爲每個新建的鏈接建立或者銷燬線程。工具

二、查詢緩存

對於SELECT語句,在解析查詢以前,服務器會先檢查查詢緩存(Query Cache),若是可以在其中找到對應的查詢,服務器就沒必要再執行查詢解析、優化和執行的整個過程,而是直接返回查詢緩存中的結果集。

但不推薦使用查詢緩存,爲何呢?由於查詢緩存每每弊大於利。

查詢緩存的失效很是頻繁,只要有對一個表的更新,這個表上全部的查詢緩存都會被清空。對於更新壓力大的數據庫來講,查詢緩存的命中率會很是低。除非你的業務就是有一張靜態表,很長時間纔會更新一次。好比,一個系統配置表,那這張表上的查詢才適合使用查詢緩存。

好在MySQL也提供了這種「按需使用」的方式。能夠將參數query_cache_type設置成DEMAND,這樣對於默認的SQL語句都不使用查詢緩存。而對於肯定要使用查詢緩存的語句,能夠用SQL_CACHE顯式指定,以下:

mysql> select SQL_CACHE * from T where ID=10;

上面也提到了MySQL8.0完全廢棄了查詢緩存的功能。

三、解析器

若是緩存沒有命中的話,MySQL會對查詢語句進行解析。簡單說解析的做用將咱們人能看懂的SQL解析成MySQ能識別的語言。

解析器先會作「詞法解析」。輸入的是由多個字符串和空格組成的一條SQL語句,MySQL須要識別出裏面的字符串分別是什麼,表明什麼。

MySQL從輸入的"select"這個關鍵字識別出來,這是一個查詢語句。它也要把字符串「T」識別成「表名T」,把字符串「ID」識別成「列ID」。

作完了這些識別之後,就要作「語法解析」。根據詞法解析的結果,語法解析器會根據語法規則,判斷輸入的這個SQL語句是否知足MySQL語法。

四、優化器

通過了解析器器,MySQL知道咱們要幹什麼。

接下來並非直接執行,而是會在優化器這一層進行優化,優化器是個很是複雜的部件,它會幫我去使用他本身認爲的最好的方式去優化這條 SQL 語句,並生成一條條的執行計劃。

例如在表裏面有多個索引的時候,決定使用哪一個索引;或者在一個語句有多表關聯(join)的時候,決定各個表的鏈接順序。好比你執行下面這樣的語句,這個語句是執行兩個表的join:

mysql> select * from t1 join t2 using(ID)  where t1.c=10 and t2.d=20;
  • 既能夠先從表t1裏面取出c=10的記錄的ID值,再根據ID值關聯到表t2,再判斷t2裏面d的值是否等於20。
  • 也能夠先從表t2裏面取出d=20的記錄的ID值,再根據ID值關聯到t1,再判斷t1裏面c的值是否等於10。

這兩種執行方法的邏輯結果是同樣的,可是執行的效率會有不一樣,而優化器的做用就是決定選擇使用哪個方案。

優化器階段完成後,這個語句的執行方案就肯定下來了,而後進入執行器階段。若是你還有一些疑問,好比優化器是怎麼選擇索引的,有沒有可能選擇錯等等,不要緊,我會在後面的文章中單獨展開說明優化器的內容。

五、執行器

MySQL經過解析器知道了你要作什麼,經過優化器知道了該怎麼作,因而就進入了執行器階段,執行器會根據一系列的執行計劃去調用存儲引擎的接口去完成SQL的執行。

開始執行的時候,要先判斷一下你對這個表T有沒有執行查詢的權限,若是沒有,就會返回沒有權限的錯誤,以下所示(在工程實現上,若是命中查詢緩存,會在查詢緩存放回結果的時候,作權限驗證。查詢也會在優化器以前調用precheck驗證權限)。

mysql> select * from T where ID=10;

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

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

好比咱們這個例子中的表T中,ID字段沒有索引,那麼執行器的執行流程是這樣的:

  1. 調用InnoDB引擎接口取這個表的第一行,判斷ID值是否是10,若是不是則跳過,若是是則將這行存在結果集中;
  2. 調用引擎接口取「下一行」,重複相同的判斷邏輯,直到取到這個表的最後一行。
  3. 執行器將上述遍歷過程當中全部知足條件的行組成的記錄集做爲結果集返回給客戶端。

至此,這個語句就執行完成了。

對於有索引的表,執行的邏輯也差很少。第一次調用的是「取知足條件的第一行」這個接口,以後循環取「知足條件的下一行」這個接口,這些接口都是引擎中已經定義好的。




參考:

【1】:《高性能MySQL》

【2】:極客時間 《MySQL實戰45講》

【3】:《MySQL技術內幕 InnoDB存儲引擎》

【4】:MySQL 8.0: Retiring Support for the Query Cache

【5】:頭條二面: 詳解一條 SQL 的執行過程

相關文章
相關標籤/搜索