當你希望MySQL能夠以更高的性能運行查詢時,最好的辦法是弄清楚MySQL是如何優化和執行查詢。《高性能MySQL》
衡量查詢開銷的三個指標
- 響應時間掃描的行數
- 服務時間(處理語句真正花的時間)
- 排隊時間(等待資源,例如IO,行鎖等)
- 掃描的行數
- 返回的行數
當刪除了搜索條件列的索引時,語句進行全表掃描,掃描的行數為5073。如圖一
圖一 掃描行數
MySQL客戶端與服務器端的通信特點
客戶端與服務器之間是半雙工通信,意味着服務器與客戶端之間的傳遞數據不可以同時發生。
- 客戶端使用一個單獨的數據包將查詢傳給服務器。當語句過長時,可能受到服務器端max_allowed_packet的限制。
- 服務器響應給用戶的數據通常會很多,由多個數據包組成。(客戶端不斷接受服務器推送的數據,客戶端沒有辦法讓服務器停下來。客戶端只能被動的接受)。
查詢的執行流程
圖二 語句的處理過程
1.連接數據庫
- 客戶端發起一條Query請求,服務器端的‘連接管理模塊’接收請求。
- 將請求轉發到‘連接進/線程模塊’。
- 調用‘用戶模塊’來進行授權檢查。
- 通過檢查后,‘連接進/線程模塊’從‘線程連接池’中取出空閑的被緩存的連接線程和客戶端請求對接,如果失敗則創建一個新的連接請求。
2.處理請求
- 查詢緩存 通過一個大小寫敏感的哈希查找判斷查詢是否命中查詢緩存的數據。
- 命中查詢緩存,用戶權限沒有問題,MySQL直接從緩存中拿結果返回給客戶端。
- 查詢優化處理(解析SQL、預處理、優化SQL的執行計划),將SQL轉化成一個執行計划。【具體過程查看 圖二】
- 解析和預處理:生成一棵解析樹(《編譯原理》的知識),MySQL按照其語法對解析樹進行驗證和解析查詢。判斷語法是否合法。這里可以對比一下存儲過程和 PHP 或者 Java 的預處理過程,它們就是因為存儲了預處理過程的結果,所以可以達到 SQL 的拼接和提高一些效率。
- 優化器和執行計划:將語法樹轉化為執行計划(子任務),並選擇成本盡量小的執行計划。
-
-
- 優化過程書上介紹了很多情況,請參考書籍6.43章
- 執行計划 MySQL會生成一個指令樹,然后通過存儲引擎完成這棵樹並返回結果 如圖2
-
- 查詢執行引擎 查詢執行引擎則根據執行計划來完成整個查詢。在執行計划時,存儲引擎通過調用實現的接口來完成。
圖三 四個表的表連接查詢的執行計划指令樹
3.返回結果
- 如果查詢可以被緩存,MySQL將結果存放到查詢緩存里。
- MySQL將結果集返回給客戶端是一個逐步返回的過程;數據庫開始產生第一個結果時,就可以開始向服務器返回結果集。
- 使用MySQL客戶端、服務器通信協議進行封包。
- 通過Tcp協議傳輸數據。