MySQL 在特定情況下對 LIMIT row_count 有專門優化 (不含 HAVING):
僅需少量行時,全表掃描可能改用索引掃描。
找到 N 個唯一值即停止掃描。
按索引順序讀取時,不計算多餘分組值。
除非使用 SQL_CALC_FOUND_ROWS。
回傳空結果集,可檢查查詢語法、取得欄位類型 (API 中)。
使用臨時表時,LIMIT 決定所需空間大小。
-- 第 100001 頁,每頁 10 筆 SELECT * FROM large_table ORDER BY id LIMIT 1000000, 10;
MySQL 必須掃描並捨棄前 1,000,000 行,再取 10 行。資料越大越慢。
-- 只用主鍵索引快速定位偏移位置,再回表取欄位
SELECT t.*
FROM large_table t
INNER JOIN (
SELECT id FROM large_table ORDER BY id LIMIT 1000000, 10
) tmp ON t.id = tmp.id;
子查詢只掃描索引 (覆蓋索引),極快;外層只回表 10 次。
-- 第一頁 SELECT * FROM large_table ORDER BY id LIMIT 10; -- 後續頁:記住上一頁最後一筆的 id SELECT * FROM large_table WHERE id > 1000010 ORDER BY id LIMIT 10;
優點:無偏移量掃描、效能恆定、適合無限滾動。
缺點:無法直接跳到指定頁碼、需唯一排序鍵。
-- 只查索引欄位 SELECT id, name FROM large_table ORDER BY id LIMIT 1000000, 10;
避免回表,但仍需掃描偏移量行。
LIMIT [offset,] row_count -- 等價寫法 LIMIT 5 -- offset=0, row_count=5 LIMIT 0, 5 -- 明確指定 LIMIT 10 OFFSET 5 -- 標準 SQL 語法 (MySQL 支援)
| 場景 | 推薦方案 | 備註 |
|---|---|---|
| 前幾頁 / 小偏移 | 直接 LIMIT | 簡單有效 |
| 中大偏移量 | 延遲關聯 | 需主鍵索引 |
| 無限滾動 / 翻頁 | 游標分頁 | 效能最佳,無法跳頁 |
| 跳轉指定頁碼 | 延遲關聯 + 緩存 | 折中方案 |
| 搜尋/篩選分頁 | Elasticsearch | 大數據量必備 |
| 變數 | 說明 | 建議 |
|---|---|---|
| sort_buffer_size | 排序緩衝區 | 大排序時調大 (如 2M-8M) |
| max_length_for_sort_data | Filesort 記錄欄位總長度上限 | 預設 1024,超過則用舊算法 |
| tmpdir | 臨時表/排序目錄 | 指向大空間、高速儲存 (NVMe) |