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

MySQL 分頁查詢最佳實踐:LIMIT 偏移量優化與大數據量效能調優

     編輯:MySQL 綜合教學

基本分頁語法

-- 第 1 頁,每頁 20 筆
SELECT * FROM product LIMIT 0, 20;

-- 第 N 頁
SELECT * FROM product LIMIT (N-1)*20, 20;

深分頁效能問題

當 OFFSET 很大時(如第 10000 頁),MySQL 需掃描並丟棄前 200,000 筆資料,導致查詢緩慢:

-- 低效:掃描 200,000 行後取 20 行
SELECT * FROM product LIMIT 200000, 20;

優化方案對比

方案適用場景原理優/缺點
子查詢 + 索引覆蓋單表、有主鍵/唯一索引先只查 ID,再回表✅ 大幅減少回表 ❌ 需覆蓋索引
延遲關聯複雜 JOIN 查詢先分頁查主鍵,再 JOIN 明細✅ 通用性強 ❌ SQL 較複雜
游標/Keyset 分頁無需跳頁、API 無限滾動WHERE id > last_id LIMIT 20✅ 極快、穩定 ❌ 不支援隨機跳頁
覆蓋索引優化只需索引欄位索引包含所有查詢欄位✅ 避免回表 ❌ 受限於查詢欄位

推薦實作:延遲關聯範例

-- 步驟 1:只查主鍵(利用索引快速定位)
SELECT id FROM product
WHERE category_id = 5
ORDER BY created_at DESC
LIMIT 200000, 20;

-- 步驟 2:用 IN 關聯查明細
SELECT * FROM product
WHERE id IN (上述查詢的 20 個 ID)
ORDER BY created_at DESC;

Java 實作範例(優化版)

public List<Product> getProducts(int pageNo, int pageSize) {
    String sql = """
        SELECT p.* FROM product p
        INNER JOIN (
            SELECT id FROM product
            WHERE category_id = ?
            ORDER BY created_at DESC
            LIMIT ?, ?
        ) tmp ON p.id = tmp.id
        ORDER BY p.created_at DESC
        """;
    // 參數: categoryId, (pageNo-1)*pageSize, pageSize
    return jdbcTemplate.query(sql, new ProductRowMapper(),
        categoryId, (pageNo - 1) * pageSize, pageSize);
}

效能測試基準

測試環境:1000 萬筆資料、InnoDB、主鍵 id、索引 (category_id, created_at)

分頁方式第 1 頁第 50000 頁
直接 LIMIT5 ms1,200 ms
延遲關聯6 ms15 ms
Keyset 分頁3 ms3 ms

選型建議

  • 後台管理/報表:延遲關聯,支援跳頁
  • APP 無限滾動/Feed 流:Keyset 分頁,效能最佳
  • 搜尋結果:評估結果集大小,必要時限制最大翻頁深度
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved