LIMIT 100000, 20 需掃描 10 萬列再丟棄WHERE id > last_id ORDER BY id LIMIT 20)為最佳SELECT * 增加 I/O 與網路傳輸-- 12c+ 標準語法(最佳)
SELECT * FROM (
SELECT t.*, ROW_NUMBER() OVER (ORDER BY id) rn
FROM my_table t
WHERE status = 1
) WHERE rn BETWEEN 11 AND 20;
-- 11g 相容寫法
SELECT * FROM (
SELECT a.*, ROWNUM rn FROM (
SELECT * FROM my_table WHERE status = 1 ORDER BY id
) a WHERE ROWNUM <= 20
) WHERE rn >= 11;
-- 2012+ 標準語法(最佳)
SELECT id, name, created_at
FROM my_table
WHERE status = 1
ORDER BY id
OFFSET 10 ROWS FETCH NEXT 10 ROWS ONLY;
-- 2005/2008 雙重 TOP 反轉法
SELECT TOP 10 * FROM (
SELECT TOP 20 * FROM my_table WHERE status = 1 ORDER BY id ASC
) AS t ORDER BY id DESC;
-- 8.0+ 視窗函數(推薦)
SELECT * FROM (
SELECT *, ROW_NUMBER() OVER (ORDER BY id) rn
FROM my_table WHERE status = 1
) t WHERE rn BETWEEN 11 AND 20;
-- 通用高效游標法(所有版本)
-- 第一頁
SELECT id, name, created_at FROM my_table WHERE status = 1 ORDER BY id LIMIT 10;
-- 後續頁(記住上一頁最大 id)
SELECT id, name, created_at FROM my_table WHERE status = 1 AND id > 1000 ORDER BY id LIMIT 10;
| 資料庫 | 版本 | 推薦語法 | 大偏移量效能 |
|---|---|---|---|
| Oracle | 12c+ | ROW_NUMBER() OVER | 優(視窗函數最佳化) |
| SQL Server | 2012+ | OFFSET/FETCH | 優 |
| MySQL | 8.0+ | ROW_NUMBER() OVER | 優 |
| MySQL | 5.7/5.6 | 游標法 (WHERE id > ?) | 優(需應用層記住游標) |
| MySQL | 所有 | LIMIT offset, size | 差(線性掃描) |
WHERE + ORDER BY掌握各資料庫原生分頁語法與游標法精髓,即可在任何量級下實現毫秒級分頁響應。