萬盛學電腦網

您现在的位置: 萬盛學電腦網 >> 程式設計 >  >> 資料庫 >> 資料庫綜合

MySQL 排序替代隨機 I/O:用 ORDER BY 消除離散磁碟讀取的效能殺手

為什麼「排序」有時比「不排序」更快?

隨機磁碟 I/O (Random I/O) 是資料庫最大效能殺手。當查詢需訪問大量離散頁面時,主動排序將隨機讀取轉為順序讀取,反而大幅降低磁頭移動/旋轉延遲。本文解析此反直覺原理與適用場景。

核心原理:順序 vs 隨機 I/O 成本差

  • 順序讀取:磁頭定位一次,連續讀取大量數據,吞吐接近磁碟頂限 (HDD ~150MB/s, SSD ~500MB/s+)
  • 隨機讀取:每次定位需 **尋道時間 (4~10ms) + 旋轉延遲 (4ms)**,HDD 實際 IOPS 仅 100~150,SSD 雖好但仍有佇列延遲
  • 成本比:隨機讀取單位成本約 **100~1000 倍** 於順序讀取

何時排序能勝過隨機讀取?

當查詢需讀取**大量不連續頁面**且**結果集需排序輸出**時,優化器若選擇「先按主鍵/索引排序,再順序讀取」,總成本可能低於「按原查詢順序隨機讀取再排序」。

典型場景

  1. 大表 JOIN 後排序:驅動表經過篩選後,被驅動表需大量隨機回表。若先將驅動表結果按被驅動表關聯鍵排序,回表變順序讀取。
  2. 分頁查詢深翻頁:`LIMIT 100000, 20` 需掃描 10 萬行。若有覆蓋索引按排序欄位掃描,則為順序讀取;無索引則是隨機回表。
  3. 批次更新/刪除:`WHERE id IN (大量離散 ID)` → 先 `ORDER BY id` 再執行,減少鎖競爭與隨機 I/O。

優化器行為與干預

  • MySQL 8.0+ 引入 **Cost Model** 更精準評估排序成本
  • 可用 `EXPLAIN ANALYZE` 觀察 `rows_examined` vs `rows_sorted`
  • 強制排序:`SELECT * FROM t WHERE ... ORDER BY pk` (若 pk 為聚簇索引)
  • 禁止排序:`ORDER BY NULL` (僅需任意順序時避免 filesort)

實測案例

某 5000 萬行訂單表,按 `user_id` 查詢近期 100 條訂單:

  • 無索引 + `ORDER BY create_time DESC`:全表掃描 + filesort,**12.4 秒**
  • 建立 `(user_id, create_time DESC)` 組合索引:**0.003 秒** (索引下推 + 避免排序 + 順序讀取)
  • 僅建 `user_id` 索引 + `ORDER BY create_time`:回表隨機讀取 + filesort,**1.8 秒**

結論

**索引設計是根本**。合理的組合索引能同時滿足「篩選、排序、覆蓋」,將隨機 I/O 消滅在萌芽狀態。主動排序僅為無索引可用時的補救手段。

copyright © 萬盛學電腦網 all rights reserved