首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> MySQL 資料庫 >> MySQL 綜合教學

MySQL 分頁優化 8 大方案深度對比:從 LIMIT 到覆蓋索引、延遲關聯、預處理

     編輯:MySQL 綜合教學

MySQL 分頁優化 8 大方案深度對比

大數據量下 LIMIT M, N 深分頁效能急劇下降 (掃描 M+N 行丟棄 M 行)。本文對比 8 種方案原理、適用場景、優缺點,附 MySQL 8.0+ 現代最佳實踐。

方案對比總覽

方案核心思路適用場景優點缺點
1. 直接 LIMIT全表掃描 + 丟棄數據量小 (<10萬)簡單深分頁極慢、結果集不穩定
2. 主鍵過濾WHERE id > offset LIMIT NID 連續、單表索引範圍掃描、快ID 不連續會漏數據、需有序
3. 索引 + ORDER BYWHERE id > offset ORDER BY id LIMIT NID 不連續、需穩定序利用索引排序、結果穩定MySQL 僅支援 ASC 索引掃描
4. PreparedStatement預編譯 + 參數化高併發重複分頁減少解析開銷、防注入本質仍是方案 3、邊界同樣
5. 覆蓋索引定位WHERE pk >= start_id ORDER BY pk LIMIT N知曉起始 ID (游標分頁)純索引掃描、極快、無 OFFSET不支援任意頁跳轉、需記錄上頁最大 ID
6. 子查詢/連接回表先查主鍵再 JOIN 回表深分頁、需任意頁跳轉減少回表次數、利用索引SQL 複雜、臨時表開銷
7. 存儲過程封裝邏輯在服務端極複雜分頁邏輯減少網絡交互難維護、業務邏輯下沉、不推薦
8. SQL_CALC_FOUND_ROWS掃全表計總數❌ 不推薦無全表掃描、5.7 已棄用、8.0 移除

深度解析:推薦方案 5 — 游標分頁 (Keyset Pagination)

原理: 記住上一頁最大主鍵 last_id,下一頁查 WHERE id > last_id ORDER BY id LIMIT 20。

-- 首頁
SELECT * FROM articles ORDER BY id DESC LIMIT 20;

-- 翻頁 (前端傳遞 last_id=1000)
SELECT * FROM articles WHERE id < 1000 ORDER BY id DESC LIMIT 20;

優勢: O(N) 複雜度、無 OFFSET 掃描、利用主鍵索引、高併發穩定。

限制: 不支援「跳到第 100 頁」、不支援雙向翻頁 (需記錄 first_id)、排序欄位必須唯一 (主鍵或唯一索引)。

方案 6 實現:延遲關聯 / 子查詢優化深分頁

需任意頁跳轉時,先在索引上定位主鍵,再回表取完整列:

-- 子查詢版
SELECT * FROM t1
WHERE id <= (SELECT id FROM t1 ORDER BY id DESC LIMIT 10000, 1)
ORDER BY id DESC LIMIT 20;

-- JOIN 版 (通常更快)
SELECT t1.* FROM t1
JOIN (SELECT id FROM t1 ORDER BY id DESC LIMIT 10000, 1) t2
  ON t1.id <= t2.id
ORDER BY t1.id DESC LIMIT 20;

原理: 內層僅掃描主鍵索引 (覆蓋索引),外層按範圍回表,避免 LIMIT 10000, 20 掃描 10020 行聚簇索引。

MySQL 8.0+ 現代最佳實踐

  1. 優先採用游標分頁 (Keyset Pagination):API 返回 next_cursor,前端無感知翻頁,效能最優。
  2. 必須任意頁跳轉:使用 LIMIT offset, size 但限制 offset < 10000,超過引導用戶用搜尋/篩選縮小範圍。
  3. 覆蓋索引優化:INDEX idx_list (status, created_at, id) 使 WHERE status=1 ORDER BY created_at DESC, id DESC LIMIT 20 純索引完成。
  4. 避免 SELECT *:只查所需欄位,配合覆蓋索引避免回表。
  5. 監控慢查詢:long_query_time=1 捕獲深分頁慢 SQL,EXPLAIN 分析 type=index vs ALL。

架構層面建議

  • 千萬級以上單表:分庫分表 (按 tenant_id/time 分片),分頁在分片內執行再合併排序。
  • 複雜條件/多表 Join 分頁:Elasticsearch 承擔檢索分頁,MySQL 只按 ID 回查詳情。
  • 緩存熱門首頁:Redis 緩存前 3 頁 JSON,降低 DB 壓力。

總結: 深分頁本質是「跳過前 N 行」的代價。**游標分頁** 從業務交互層面消除 OFFSET,是根治方案;配合**覆蓋索引**、**讀寫分離**、**分庫分表**,可支撐億級數據分頁。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved