SELECT * FROM cp_mo100227 WHERE cpid=769 LIMIT 888888, 10;
-- 執行時間:3.84 秒
原因:MySQL 需先掃描 offset + limit 行(888,898 行),再丟棄前 888,888 行,全是無效 IO。
limit 行數據。SELECT id, substr(mobile,1,7), time, cpid, linkid
FROM cp_mo100227 WHERE cpid=769 LIMIT 888888, 10;
-- 3.84 秒
SELECT id, substr(mobile,1,7), time, cpid, linkid
FROM cp_mo100227
WHERE cpid=769
AND id >= (SELECT id FROM cp_mo100227 WHERE cpid=769 ORDER BY id LIMIT 888888, 1)
LIMIT 10;
-- 0.00 秒
SELECT id, substr(mobile,1,7), time, cpid, linkid
FROM cp_mo100227
WHERE cpid=769
AND time >= '2010-02-24 21:07:48'
LIMIT 10;
-- 0.01 秒
cpid=769 有索引支援(聯合索引 idx_cpid_id 或 idx_cpid_time 最佳)。| 場景 | 優化手段 | 代碼範例 |
|---|---|---|
| 小偏移量 (< 1000) | 直接 LIMIT,無需優化 | LIMIT 10, 20 |
| 大偏移量,有單調遞增列 | 子查詢定位主鍵/時間 | WHERE id >= (SELECT id ... LIMIT offset,1) LIMIT size |
| 大偏移量,無單調列 | 覆蓋索引 + 子查詢 | WHERE pk IN (SELECT pk FROM tbl ... LIMIT offset, size) |
| 無限滾動/游標分頁 | 游標式(推薦) | WHERE id > last_id ORDER BY id LIMIT 20 |
| 後台管理必須跳頁 | 預計算總頁數 + 緩存首頁/熱門頁 | Redis 緩存前 100 頁 HTML 片段 |
MySQL JOIN 採用 Nested Loop Join(嵌套循環)。
原則:用小結果集驅動大結果集,而非單純「小表驅動大表」。
LEFT JOIN時,從表條件寫 ON 後,主表條件寫 WHERE 後,否則退化為內連接。
LIMIT 大偏移量 = 全表掃描的偽裝。
核心解法:**覆蓋索引定位主鍵 + 游標分頁**。
實測從 3.84s 降至 0.00s,**提升 3800 倍**。
請立即檢查代碼庫中所有 LIMIT offset, size 且 offset > 10000 的查詢,逐個優化。