傳統 LIMIT offset, size 在大偏移量下效能崩塌(需掃描並捨棄前 N 筆)。本文揭示從基礎優化到生產級方案的完整演進路徑。
SELECT * FROM t ORDER BY id LIMIT 1000000, 10; -- 數十秒
SELECT * FROM t WHERE id >= (SELECT id FROM t ORDER BY id LIMIT 1000000, 1) LIMIT 10; -- 0.x 秒
SELECT * FROM t WHERE id BETWEEN 1000000 AND 1000010; -- 比上快 5-10 倍
核心洞察:WHERE 條件欄位 + ORDER BY/LIMIT 使用的主鍵建立複合索引,且僅查主鍵可走索引覆蓋掃描。
-- 針對 vtype=1 分頁場景
ALTER TABLE collect ADD INDEX idx_vtype_id (vtype, id);
-- 第一階段:只查主鍵,走覆蓋索引,極快
SELECT id FROM collect WHERE vtype=1 ORDER BY id LIMIT 90000, 10; -- 0.04 秒
-- 第二階段:用 IN 查詢回表取完整欄位
SELECT id, title, url ... FROM collect WHERE id IN (90000, 90001, ...); -- 0 秒級
$sql = "SELECT id FROM collect WHERE vtype=$vtype ORDER BY id";
$db->execute($sql);
$ids = [];
while ($row = $db->fetch_array()) $ids[] = $row['id'];
$id_str = implode(',', $ids);
$db->pagesize = 0; // 關閉分頁
$db->execute("SELECT id,title,url,... FROM collect WHERE id IN ($id_str)");
// 輸出結果 + 分頁導航
IN (主鍵列表) 同樣走索引查找,極高效LIMIT 900000,10 耗時 0.04 秒LIMIT 需 8-9 秒