SELECT * FROM cyclopedia LIMIT 90000, 100; -- 8.88 秒
MySQL 必須掃描前 90,000 行並丟棄,再取 100 行。隨 OFFSET 增大線性惡化。
利用主鍵 ID 有序、唯一、聚簇索引特性:
ID 找到目標起始點。| SQL | 耗時 | 原理 |
|---|---|---|
SELECT * FROM cyclopedia LIMIT 90000, 100 | 8.88 秒 | 全掃描 90,100 行 |
SELECT * FROM cyclopedia WHERE ID >= (SELECT ID FROM cyclopedia ORDER BY ID LIMIT 90000, 1) LIMIT 100 | 0.06 秒 | 子查詢只取 1 個 ID(索引定位),外查詢範圍掃 100 行 |
SELECT * FROM cyclopedia WHERE ID >= (SELECT MAX(ID) FROM (SELECT ID FROM cyclopedia ORDER BY ID LIMIT 90001) t) LIMIT 100 | 0.23 秒 | 子查詢掃 90,001 行取 MAX,較慢 |
SELECT * FROM cyclopedia
WHERE ID >= (SELECT ID FROM cyclopedia ORDER BY ID LIMIT 90000, 1)
LIMIT 100;
ORDER BY ID LIMIT offset, 1 走主鍵索引,極快定位單一 ID。WHERE ID >= target_id LIMIT page_size 走主鍵範圍掃描,只讀需求行。ID 的子查詢觸發 Index Only Scan(覆蓋索引),不回表。若前端支援「上一頁/下一頁」而非跳頁碼:
-- 首頁
SELECT * FROM cyclopedia ORDER BY ID LIMIT 100;
-- 下一頁(記住上頁最大 ID)
SELECT * FROM cyclopedia WHERE ID > 90099 ORDER BY ID LIMIT 100;
| 資料庫 | 語法 |
|---|---|
| MySQL / PostgreSQL / SQLite | LIMIT 100 OFFSET 90000 / LIMIT 90000, 100 |
| SQL Server | SELECT * FROM (SELECT *, ROW_NUMBER() OVER (ORDER BY id) rn FROM t) x WHERE rn BETWEEN 90001 AND 90100 |
| Oracle 12c+ | SELECT * FROM t ORDER BY id OFFSET 90000 ROWS FETCH NEXT 100 ROWS ONLY |
| Oracle 11g- | SELECT * FROM (SELECT a.*, ROWNUM rn FROM (SELECT * FROM t ORDER BY id) a WHERE ROWNUM <= 90100) WHERE rn > 90000 |
WHERE cat=1 ORDER BY id LIMIT 100 需 INDEX (cat, id)。MySQL 深分頁優化核心:用子查詢在索引上定位起始主鍵,外層範圍掃描取資料。將 O(N) 全掃描降為 O(log N + page_size) 索引查找。配合游標分頁模式,徹底解決大資料集分頁效能問題。