MySQL的深度分頁如何優化!

MySQL深度分頁(例如 LIMIT 1000000, 20)性能差的主要原因在于 OFFSET 需要掃描并跳過大量數據,即使這些數據最終并不返回。隨著 OFFSET 增大,性能會急劇下降。

以下是優化深度分頁的常用策略,根據場景選擇最適合的方案:

🛠 1. 使用覆蓋索引 + 延遲關聯 (最常用且有效)

  • 核心思想:
    • 先利用覆蓋索引快速找到目標分頁行的主鍵(避免回表)。
    • 再根據這些主鍵回表關聯獲取完整的行數據。
  • 優化前 (性能差):
    SELECT * FROM your_table ORDER BY sort_column LIMIT 1000000, 20;
    
  • 優化后:
    SELECT t.*
    FROM your_table t
    JOIN (SELECT id -- 只選擇主鍵FROM your_tableORDER BY sort_column -- 確保有 (sort_column, id) 或類似索引LIMIT 1000000, 20
    ) AS tmp ON t.id = tmp.id; -- 通過主鍵關聯回原表
    
  • 為什么有效:
    • 子查詢 SELECT id ... LIMIT 1000000, 20 利用了覆蓋索引(僅包含 sort_columnid 的索引)。數據庫引擎只需掃描索引結構就能找到這 20 行的 ID,速度非常快(索引通常比表數據小得多,且在內存中可能性高)。
    • 外層查詢 SELECT t.* ... 只需要精確地根據這 20 個 ID 回表查詢完整數據,效率極高。
  • 關鍵:
    • 必須創建合適的索引: 通常是 (sort_column, id)(sort_column, other_columns_in_where)。確保子查詢能夠使用覆蓋索引。如果 sort_column 本身是主鍵或唯一索引,直接用 (sort_column) 即可。
    • 適用于排序字段相對穩定的情況。

🔍 2. 基于游標/連續分頁 (Cursor-based Pagination / Keyset Pagination)

  • 核心思想: 放棄使用 OFFSET,改為記住上一頁最后一條記錄的排序字段值(或多個字段值),作為下一頁的起始點。
  • 優化前:
    -- Page 1
    SELECT * FROM orders ORDER BY created_at DESC, id DESC LIMIT 20;
    -- Page 2 (慢!)
    SELECT * FROM orders ORDER BY created_at DESC, id DESC LIMIT 20 OFFSET 20;
    
  • 優化后:
    -- Page 1
    SELECT * FROM orders ORDER BY created_at DESC, id DESC LIMIT 20;
    -- 假設最后一條記錄: created_at = '2023-10-25 14:30:00', id = 12345
    -- Page 2 (快!)
    SELECT * FROM orders
    WHERE (created_at < '2023-10-25 14:30:00') OR(created_at = '2023-10-25 14:30:00' AND id < 12345)
    ORDER BY created_at DESC, id DESC
    LIMIT 20;
    
  • 為什么有效:
    • 完全避免了 OFFSET 的掃描跳過操作。
    • 查詢利用了 (created_at DESC, id DESC) 索引進行高效的范圍查找,只掃描需要的行。
  • 關鍵:
    • 需要一個唯一且穩定的排序鍵: 通常使用時間戳(如 created_at)或自增主鍵(如 id),或者它們的組合(如上例,防止 created_at 重復時順序不確定)。
    • 適用于連續瀏覽場景: 如無限滾動、上一頁/下一頁導航。不支持直接跳轉到任意頁碼
    • 需要客戶端存儲"游標"(即上一頁最后記錄的排序鍵值)。
    • 處理新增/刪除數據時順序變化相對穩定(取決于排序鍵)。

📊 3. 預先計算 & 物化視圖 (Precomputation & Materialized Views)

  • 核心思想: 對于復雜查詢或聚合分頁,將結果預先計算并存儲在一個專門的分頁表或物化視圖中。
  • 實現:
    • 創建一個新表,包含原始表的主鍵、排序字段、以及其他分頁需要的聚合/計算字段。
    • 使用定時任務(Cron, Event Scheduler)或觸發器(謹慎使用,性能開銷大)或變更數據捕獲(CDC)來維護這個表。
    • 對這個新表進行分頁查詢(可以使用延遲關聯或游標)。
  • 為什么有效:
    • 將復雜查詢的開銷分攤到預計算階段。
    • 分頁查詢的目標表更小、結構更簡單、索引更優化。
  • 適用場景:
    • 報表分頁、需要復雜聚合的分頁、數據相對靜態或可以接受一定延遲的場景。
    • 不適合需要實時最新數據的場景。

🔄 4. 分區 (Partitioning)

  • 核心思想: 將大表物理分割成更小的、更易管理的片段(分區)。分頁查詢可以限定在特定分區內進行。
  • 實現:
    • 按范圍(如 created_at 年份、月份)或列表(如 region)分區。
    • 在查詢中顯式指定分區或利用分區剪裁(WHERE 條件匹配分區鍵)。
    -- 假設按年份分區
    SELECT * FROM your_table PARTITION (p2023)
    ORDER BY sort_column
    LIMIT 1000000, 20; -- 即使有 OFFSET, 但掃描的數據量僅限 2023 分區
    
  • 為什么有效:
    • 顯著減少單次查詢需要掃描的數據量(從全表掃描變為分區掃描)。
  • 關鍵:
    • 分區鍵的選擇至關重要,必須與分頁查詢的 WHERE 條件或排序強相關才能有效剪裁。
    • 分區本身不能解決分區內深度分頁的 OFFSET 問題,分區內數據量過大時仍需結合延遲關聯或游標。
    • 分區管理和維護有額外開銷。

?? 5. 其他考慮與權衡

  • 避免 SELECT *: 只查詢需要的列,減少數據傳輸和內存占用。
  • 優化 WHERE 條件: 盡可能縮小初始數據集。有效的 WHERE 條件是所有優化的基礎。
  • 前端/產品設計:
    • 限制可訪問的頁數(例如,只允許訪問前 100 頁)。
    • 鼓勵使用搜索/過濾縮小結果集,而不是無限制翻頁。
    • 對于"跳轉到最后一頁"這種需求,考慮顯示總條目數并提供輸入框跳轉,但實現時可能需要估算或緩存總數。
  • 分庫分表 (Sharding): 終極方案,當單機容量和性能達到極限時。將數據分散到多個物理數據庫/表中。分頁查詢會變得非常復雜,通常需要中間件或應用層聚合。
  • 緩存: 對特定查詢模式(如熱門的前幾頁)進行結果緩存。

📌 總結建議

  1. 首選嘗試延遲關聯 (覆蓋索引): 適用于大多數場景,對應用層改動較小,效果顯著。關鍵是創建正確的覆蓋索引。
  2. 對于連續瀏覽場景 (無限滾動/上下一頁): 強烈推薦游標分頁: 性能最優,無 OFFSET 瓶頸。需要應用層配合存儲游標。
  3. 復雜聚合/報表分頁: 考慮預計算/物化視圖: 將計算壓力轉移到后臺。
  4. 海量數據且訪問模式可分區: 結合分區 + 上述技巧 (延遲關聯/游標): 減少單次掃描范圍。
  5. 審視需求: 是否真的需要深度隨機跳頁?優化產品設計往往是性價比最高的方案。
  6. 監控與分析: 使用 EXPLAIN 分析查詢執行計劃,確認是否使用了預期的索引。

選擇哪種方案取決于你的具體數據量、訪問模式、排序需求、實時性要求以及對應用層改動的接受程度。通常 延遲關聯游標分頁 是解決深度分頁性能問題最直接有效的武器💪。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/87515.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/87515.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/87515.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

K8s Pod 調度基礎——1

目錄 一、Replication Controller&ReplicaSet ?一、Replication Controller (RC)? ?原理? ?特性? ?意義? ?示例與逐行解釋? ?二、ReplicaSet (RS)? ?原理? ?特性? ?意義? ?示例與逐行解釋? ?三、RC 與 RS 的對比? ?四、總結? 二、Dea…

C# Task異步的常用方法

Task異步的常用方法 C# 中的 Task 類是 System.Threading.Tasks 命名空間的一部分&#xff0c;用于表示異步操作。 一、Task.Run(Action action): 此靜態方法用于在后臺運行一個新任務&#xff0c;并返回與該任務關聯的 Task 實例。 本質是將任務放入線程池執行&#xff0c;自…

OpenResty實戰之PB級物聯網數據處理:時序數據庫優化實戰

某智慧能源平臺通過本方案成功處理了日均1.2萬億數據點&#xff0c;存儲成本降低70%&#xff0c;查詢延遲從分鐘級優化到亞秒級。本文將深入解析PB級物聯網數據處理的核心挑戰與時序數據庫深度優化技巧。 一、物聯網數據特性與存儲挑戰 1.1 物聯網數據核心特征 #mermaid-svg-U…

聊聊架構(5)數字化時代的平臺商業架構

在數字化浪潮的推動下&#xff0c;平臺經濟已成為全球經濟增長的關鍵驅動力。作為架構師&#xff0c;不僅要精通架構設計的基礎方法論&#xff0c;還需具備敏銳的商業洞察力。架構的價值在于服務業務和商業&#xff0c;而業務的發展又促使架構不斷演進。本文將深入探討平臺的商…

【數據增強】精細化貼圖數據增強

1.任務背景 假設我有100個蘋果的照片&#xff0c;我需要把這些照片粘貼到傳送帶照片上&#xff0c;模擬“傳送帶蘋果檢測”場景。 這種貼圖的方式更加合理一些&#xff0c;因為yolo之類的mosaic貼圖&#xff0c;會把圖像弄的非常支離破碎。 現在我需要隨機選擇幾張蘋果圖像&am…

HTML響應式Web設計

什么是響應式Web設計&#xff1f; RWD指的是響應式Web設計&#xff08;Responsive Web Design)RWD能夠以可變尺寸傳遞網頁RWD對于平板和移動設備是必需的 創建一個響應式設計&#xff1a; <!DOCTYPE html> <html lang"en-US"> <head> <styl…

【讀代碼】百度開源大模型:ERNIE項目解析

一、項目基本介紹 1.1 項目概述 ERNIE(Enhanced Representation through kNowledge IntEgration)是百度基于PaddlePaddle深度學習框架開發的多模態預訓練模型體系。最新發布的ERNIE 4.5系列包含10個不同變體,涵蓋從300B參數的巨型MoE模型到0.3B的輕量級模型,形成完整的多…

2025年6月:技術探索與生活平衡的協奏曲

> 當代碼與晨跑軌跡在初夏的陽光下交織,我找到了程序員生活的黃金分割點 --- ### 一、技術突破:AI驅動的智能工作流優化系統 這個月我成功部署了第三代自動化工作流系統,核心創新在于**動態決策樹+實時反饋機制**。系統可自主優化處理路徑,錯誤率下降62%! ```pyth…

如何查看服務器運行了哪些服務?

&#x1f7e2; 一、Linux服務器Linux下&#xff0c;常用以下幾種方法&#xff1a;? 1. 查看所有正在監聽端口的服務netstat -tulnp 含義&#xff1a;-t TCP-u UDP-l 監聽狀態-n 顯示端口號-p 顯示進程號和程序名示例輸出&#xff1a;pgsql復制編輯Proto Recv-Q Send-Q Local A…

【Linux基礎知識系列】第三十八篇 - 打印系統與 PDF 工具

在Linux系統中&#xff0c;打印和PDF處理是日常辦公和文檔管理中不可或缺的功能。CUPS&#xff08;Common Unix Printing System&#xff09;是Linux中常用的打印服務&#xff0c;它提供了打印任務的管理和打印設備的配置功能。同時&#xff0c;Linux也提供了多種PDF處理工具&a…

STM32CUBEMX 使用教程6 — TIM 定時器配置、定時中斷

往期文章推薦&#xff1a; STM32CUBEMX 使用教程5 — DMA配置 & 串口結合DMA實現數據搬運 STM32CUBEMX 使用教程4 — 串口 (USART) 配置、重定向 printf 輸出 STM32CUBEMX 使用教程3 — 外部中斷&#xff08;EXTI&#xff09;的使用 STM32CUBEMX 使用教程2 — GPIO的使…

微信小程序實現table表格

微信小程序沒有table標簽&#xff0c;運用display:table和display:flex實現一個內容字數不固定表格…… wxml&#xff1a; <view class"ContentShow"> <view class"conht">煙臺市新聞發布會登記審批表</view> <view class"tabl…

MySQL 基本面試題

目錄 一、SQL的基本操作 1、SQL查詢的執行順序 2、count(*)、count(1) 、count(列名) 的區別 3、char 和 varchar 的區別 4、MySQL 中常用的基礎函數 5、MySQL的執行流程 6、MyISAM和InnoDB的區別 二、事務 1、事務的基本概念 2、事務的四大特性&#xff08;ACID) 3…

WPF學習筆記(12)下拉框控件ComboBox與數據模板

下拉框控件ComboBox與數據模板 一、ComboBox1. ComboBox概述2. ItemsControl類3. Selector類4. ComboBox類 二、ComboBox數據模板總結 一、ComboBox 1. ComboBox概述 ComboBox類代表一個有下拉列表的選擇控件&#xff0c;供用戶選擇。 官方文檔&#xff1a;https://learn.mic…

Docker for Windows 設置國內鏡像源教程

在使用 Docker 時&#xff0c;由于默認的 Docker Hub 鏡像源位于國外&#xff0c;國內用戶在拉取鏡像時可能會遇到速度慢或連接不穩定的問題。為了加速鏡像拉取&#xff0c;可以將 Docker 配置為使用國內鏡像源。以下是適用于 Windows 系統的詳細配置方法&#xff1a; 方法一&…

一鍵部署AI工具!用AIStarter快速安裝ComfyUI與Stable Diffusion

AIStarter部署AI工具&#xff0c;讓AI開發更簡單&#xff01;無需研究復雜環境配置&#xff0c;AIStarter平臺提供一鍵安裝ComfyUI和Stable Diffusion&#xff0c;支持多版本選擇&#xff0c;快速上手。以下是詳細步驟&#xff1a; 一、訪問AIStarter市場 下載AIStarter&#x…

Python基礎(吃洋蔥小游戲)

下面我將為你設計一個"吃洋蔥小游戲"的Python實現方案&#xff0c;使用Pygame庫開發。這個游戲模擬吃洋蔥的過程&#xff0c;玩家需要收集不同種類的洋蔥以獲得高分&#xff0c;同時避免吃到辣椒。 &#x1f9c5; 吃洋蔥小游戲 - Python實現方案 &#x1f3ae; 1. …

Objective-C 路由表原理詳解

在 Objective-C 中實現路由表是組件化架構的核心&#xff0c;它通過 URL 映射機制實現模塊間解耦通信。以下是完整實現原理&#xff1a; 一、核心架構設計 #mermaid-svg-5jMinPiZe8mivAbi {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fil…

通過交互式網頁探索傳輸現象-AI云計算數值分析和代碼驗證

傳輸過程涉及質量、動量和能量等物理量在各種系統中的基本運動和轉移&#xff0c;主要分為動量傳輸、熱量傳輸和質量傳輸&#xff0c;在工程、環境科學、生物學和物流等領域至關重要。 傳輸過程是指物理量&#xff08;如質量、動量和能量&#xff09;在物理、化學、生物或工程系…

使用Rust原生實現小波卡爾曼濾波算法

一、算法原理概述小波變換&#xff08;Wavelet Transform&#xff09;通過多尺度分解將信號分為高頻&#xff08;細節&#xff09;和低頻&#xff08;近似&#xff09;部分&#xff0c;高頻通常包含噪聲&#xff0c;低頻保留主體信息。使用Haar小波&#xff08;計算高效&#x…