首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> MySQL 資料庫 >> MySQL 綜合教學

《高效能 MySQL》查詢效能優化核心筆記:生命週期、訪問優化、重構策略、執行引擎

     編輯:MySQL 綜合教學

《高效能 MySQL》查詢效能優化核心筆記

系統梳理查詢生命週期、資料訪問優化、查詢重構策略、MySQL 客戶端/服務端協議、查詢快取、優化器原理、關聯執行機制、排序優化、執行引擎、結果返回機制六大核心模組。

一、查詢生命週期與慢的根因


客戶端 → 服務器 → 解析 → 優化器生成執行計劃 → 執行(存儲引擎交互) → 返回結果

核心洞察:查詢慢 90%+ 因**訪問資料過多**(掃描行數 ≫ 返回行數)。優化本質:**減少資料訪問量**。

二、優化資料訪問:兩大檢視點

  1. 應用層:是否請求了不需要的資料?
    — SELECT *、多表關聯全欄位、重複查詢同資料、未加 LIMIT 的大結果集。
    — 對策:精確列表、覆蓋索引、應用層快取、分頁限制。
  2. 服務器層:MySQL 是否掃描了過多行?
    — 三大指標:**響應時間**、**掃描行數**、**返回行數**(慢日誌均記錄)。
    — 理想:掃描行數 ≈ 返回行數;典型比率 1:1 ~ 10:1。
    — 訪問類型(EXPLAIN type):system > const > eq_ref > ref > range > index > ALL。

三、WHERE 條件應用三層次(由優到劣)

  1. 存儲引擎層索引過濾:索引直接定位匹配行,最省 I/O。
  2. 服務器層覆蓋索引掃描:Using index,索引滿足所有需求列,無需回表。
  3. 服務器層回表後過濾:Using where,先回表讀全行再過濾,最費 I/O。

四、查詢重構四大策略

策略核心思想適用場景
拆分大查詢大 DELETE/UPDATE 分批次,減少鎖持有、日誌膨脹、復制延遲定期清理歷史資料、大批量狀態變更
分解關聯查詢JOIN 拆為多單表查詢,應用層組裝緩存命中率高、鎖競爭大、需按 ID 順序讀取
切分複雜邏輯將超大 SQL 拆解為多簡單 SQL優化器統計不足導致計劃劣化時
冗余/匯總表預計算聚合結果,查詢直接讀匯總表儀表板、報表、高頻統計

五、MySQL 客戶端/服務端半雙工協議

  • 任一時刻單向傳輸:要麼客戶端發請求,要麼服務端推結果。
  • max_allowed_packet 限制單包大小,大查詢/大結果需調大。
  • 結果集**流式推送**:服務端生成第一行即開始推送,客戶端不可中途截斷(只能粗暴斷連)。
  • mysql_unbuffered_query() (PHP) / 游標模式:避免客戶端驅動全量緩存結果集,節省記憶體。

六、查詢快取機制與局限

  • 哈希匹配(大小寫敏感),命中則跳過解析/優化/執行,直接返回結果(含權限檢查)。
  • 任意表寫入即失效相關快取,**寫多讀少場景快取命中率極低、反成負擔**。
  • MySQL 8.0 移除查詢快取,建議應用層快取替代。

七、優化器與關聯執行

  • 基於成本優化器:成本單位 = 隨機讀 4K 頁代價,統計資訊(頁數、基數、長度、分佈)驅動決策。
  • 關聯算法:**嵌套循環關聯**,驅動表逐行 → 被驅動表索引查找匹配。
  • 執行計劃:左側深度優先樹,EXPLAIN EXTENDED + SHOW WARNINGS 可見重寫後 SQL。
  • 搜索空間:n 表關聯 n! 種順序,超過 optimizer_search_depth 改貪婪搜索。

八、排序優化:兩代算法與臨時表陷阱

臨時表陷阱:關聯查詢 + ORDER BY 非驅動表欄位 → Using temporary; Using filesort,即使 LIMIT 10 也會先建全量臨時表再排序,極慢。

九、執行引擎與 Handler API

  • 優化階段為每表建立 handler 實例,獲取欄位/索引統計資訊。
  • 底層僅幾十個介面(如 index_first、index_next、rnd_next),像積木組合完成複雜操作。

十、結果返回增量流式

  • 最後關聯完成、第一行就緒即開始推送,服務端無需緩存全量結果。
  • 雙重優勢:服務端記憶體穩定、客戶端最快拿到首行資料。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
算法特點代價
兩次傳輸 (舊)讀排序鍵+行指針 → 排序 → 再按指針回表讀數據大量隨機 I/O,慢
單次傳輸 (新)一次讀取所有需求列 → 內存排序 → 直接返回順序 I/O,快;但佔用更多 sort_buffer