第一講:一條 SQL 查詢語句是如何執行的
總覽圖示
MySQL 查詢的執行流程可以大致分為以下步驟(如圖所示):
- 連接器(Connection)
- 查詢緩存(Query Cache,MySQL 8.0 已廢棄)
- 分析器(Parser)
- 優化器(Optimizer)
- 執行器(Executor)
整個 MySQL 架構分為 Server 層 與 存儲引擎層(Storage Engine):
Server 層 | 存儲引擎層 |
---|---|
連接器、查詢緩存、分析器、優化器、執行器、內置函數、觸發器、視圖、存儲過程等 | 數據的實際存儲與讀取,支持 InnoDB、MyISAM、Memory 等引擎 |
一、連接器(Connector)
負責管理客戶端連接、驗證身份、權限檢查及連接生命周期維護。
mysql -h<ip地址> -P<端口> -u<用戶名> -p
工作流程:
- 驗證用戶身份:連接后輸入密碼,系統校驗用戶名/密碼是否正確。
- 權限校驗:認證通過后,系統會從權限表讀取用戶權限。更改權限后需重新連接才能生效。
- 連接狀態管理:長時間不操作,連接會因
wait_timeout
參數超時自動斷開(默認8小時)。 - 長連接問題:
- 長連接可減少連接頻率,但可能導致內存膨脹。
- 推薦措施:
- 定期斷開或重置連接。
- 使用
mysql_reset_connection
(MySQL 5.7+)釋放連接資源,但不需重新驗證權限。
二、查詢緩存(Query Cache)
說明:MySQL 8.0 已徹底移除查詢緩存功能,以下內容適用于舊版本。
工作原理:
- 執行
SELECT
語句前,先檢查是否有完全相同的 SQL 已執行過并緩存在內存中(key=語句文本,value=結果集
)。 - 命中緩存則直接返回結果,跳過后續步驟。
- 未命中則執行后續流程,并將結果緩存。
使用建議:
-
查詢緩存對動態更新頻繁的表幾乎無效,一旦表被修改,與其相關的所有緩存都會失效。
-
只適合查詢頻率高、更新頻率低的靜態表(如配置表)。
-
推薦按需使用:
SELECT SQL_CACHE * FROM T WHERE ID=10;
三、分析器(Parser)
將 SQL 文本轉換為數據庫能識別的結構形式(語法分析 + 詞法分析)。
功能:
- 詞法解析:識別關鍵詞、表名、字段名等組成部分。
- 語法檢查:驗證 SQL 是否符合語法規范。
示例:
elect * from t where ID=1;
報錯信息:
ERROR 1064 (42000): You have an error in your SQL syntax;
錯誤提示會定位到第一個出錯的位置,關注提示中的 use near
即可定位錯誤代碼段。
四、優化器(Optimizer)
SQL 有多種執行方式,優化器選擇最優執行路徑。
功能:
- 決定使用哪個索引(如多索引場景)
- 決定多表
JOIN
順序(不同順序會影響執行效率)
示例:
SELECT * FROM t1 JOIN t2 USING(ID) WHERE t1.c=10 AND t2.d=20;
兩種執行方案:
- 先查
t1.c=10
,再連表t2
判斷t2.d=20
- 先查
t2.d=20
,再連表t1
判斷t1.c=10
優化器會選擇代價(成本)最低的執行路徑。
五、執行器(Executor)
執行器按優化器選擇的方案實際執行查詢語句。
流程:
- 權限檢查:再次驗證用戶是否對該表有查詢權限。
- 調用引擎接口:根據是否有索引,選擇不同的數據讀取方式。
無索引執行流程:
SELECT * FROM T WHERE ID=10;
執行器會:
- 順序讀取每一行(全表掃描)
- 判斷是否滿足
ID=10
條件 - 滿足則加入結果集
- 返回所有結果集給客戶端
有索引執行流程:
- 使用索引快速定位滿足條件的記錄。
- 使用“滿足條件的第一行” → “下一行”的迭代接口。
- 查詢效率顯著提升。
在慢查詢日志中可以看到 Rows_examined
字段,即執行過程中掃描的數據行數。