EXPLAIN SELECT * FROM message ORDER BY id DESC LIMIT 10000, 20;
-- rows: 10020 → 掃描 10020 列,丟棄 10000 列
隨著 Offset 增大,掃描列數線性增長,IO 與 CPU 雙重壓力。
-- 步驟 1: 只掃主鍵索引取目標 ID (覆蓋索引,極快)
SELECT id FROM message ORDER BY id DESC LIMIT 10000, 1;
-- 步驟 2: 主查詢直接定位範圍
SELECT * FROM message
WHERE id <= (上一步取得的 ID)
ORDER BY id DESC LIMIT 20;
實測:100,000 Offset 從 0.18s 降至 0.06s (3 倍提升)。
-- 當前頁 ID 範圍 [9500, 9527] (DESC 排序)
-- 下一頁
SELECT * FROM message WHERE id < 9500 ORDER BY id DESC LIMIT 20;
-- 上一頁
SELECT * FROM message WHERE id > 9527 ORDER BY id ASC LIMIT 20; -- 記得應用層反轉
-- 當前頁 ID 範圍 [9500, 9527],每頁 20 筆
-- 跳第 8 頁 (往前 2 頁,偏移 40)
SELECT * FROM message WHERE id > 9527 ORDER BY id ASC LIMIT 40, 20;
-- 跳第 13 頁 (往後 3 頁,偏移 60)
SELECT * FROM message WHERE id < 9500 ORDER BY id DESC LIMIT 60, 20;
原理:以當前頁邊界 ID 為基準,計算相對偏移,避免從頭掃描。
| 場景 | 推薦方案 | 關鍵索引 |
|---|---|---|
| 後台管理、小偏移 | 直接 LIMIT | (sort_col) |
| 前台列表、大偏移、需頁碼 | 延遲關聯 | (sort_col, pk) 覆蓋索引 |
| 無限滾動、App 瀑布流 | 游標式 | (sort_col, pk) |
| 論壇翻頁、需跳頁 | 相對偏移 | (sort_col, pk) |
已在 60 萬資料表驗證:延遲關聯與相對偏移在深分頁 (10 萬+) 效能**提升 10-20 倍**,游標式效能恆定最優。