深分頁性能問題分析與優化實踐

在日常測試工作中,我們經常會遇到分頁查詢接口,例如:

GET /product/search?keyword=&pageNum=1&pageSize=10

乍看之下,這樣的分頁接口似乎并無性能問題,響應時間也很快。但在一次性能壓測中,我們復現了一個典型的深分頁性能瓶頸,并深入分析了其成因與優化思路,本文記錄該過程與結論。

📌 壓測背景

接口路徑:/product/search

功能描述:根據關鍵字模糊查詢商品列表,支持分頁(pageNum, pageSize)。

? 數據規模
為了模擬真實生產場景,我們使用以下 SQL 批量造數,構造了 100萬+商品數據(pms_product 表):


SET @max_id := (SELECT IFNULL(MAX(id), 0) FROM pms_product);
SET @row := 0;INSERT INTO pms_product (id, brand_id, product_category_id, name, sub_title, price,publish_status, verify_status, sort, description, delete_status,new_status, recommand_status, sale, stock, low_stock, unit, weight,preview_status, service_ids, keywords, note, product_sn
)
SELECT @max_id + seq AS id,FLOOR(1 + RAND() * 10),FLOOR(1 + RAND() * 10),CONCAT('商品-', @max_id + seq),'',ROUND(RAND() * 1000, 2),1, 1, @max_id + seq, '', 0, 1, 1, 100, 100, 10, '', 1.5, 1,'1,2,3', '', '', CONCAT('SN', LPAD(@max_id + seq, 6, '0'))
FROM (SELECT @row := @row + 1 AS seqFROM (SELECT 0 UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) t1,(SELECT 0 UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) t2,(SELECT 0 UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) t3,(SELECT 0 UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) t4,(SELECT 0 UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) t5,(SELECT @row := 0) rLIMIT 100000
) temp;

數據字段包含多個維度如:商品分類、品牌、價格、上下架狀態、是否刪除等。

🔍 性能壓測結果對比

我們使用 JMeter 對分頁接口進行了壓測,以下是對比結果:
正常分頁壓測結果:
在這里插入圖片描述
深分頁壓測結果:
在這里插入圖片描述

🚩 分頁頁碼:pageNum=1(正常分頁)

樣本數平均響應時間最大響應時間吞吐量 (TPS)平均返回字節數
102263ms2419ms3.2/sec9317 字節

🚩 分頁頁碼:pageNum=100000(深分頁)

樣本數平均響應時間最大響應時間吞吐量 (TPS)平均返回字節數
103245ms3653ms2.4/sec4224 字節

🧠 為什么深分頁會變慢?
? 1. Offset 越大,代價越高
分頁底層使用 LIMIT offset, size,如:
1)深分頁執行的sql:
在這里插入圖片描述


SELECT * FROM pms_product 
WHERE delete_status = 0 AND publish_status = 1 
ORDER BY id 
LIMIT 99990, 10;

該查詢需要:

  • 遍歷前 100000 行(offset),丟棄
  • 返回最后 10 行

即使加了索引,MySQL 也必須掃描 offset + limit 條數據后再丟棄前面。
2)正常分頁執行的sql:
在這里插入圖片描述

SELECT count(0) FROM pms_product WHERE delete_status = 0 AND publish_status = 1;
SELECT ... FROM pms_product WHERE delete_status = 0 AND publish_status = 1 LIMIT 10;

? 結論:

  • LIMIT 10 是在數據前面截取的,性能還行,Rows_examined掃描了28行;
  • count(0) 已掃描 100w 行(較慢);

? 2. explain 顯示沒有使用覆蓋索引
我們對深分頁 SQL 執行了 EXPLAIN 分析:


EXPLAIN SELECT * FROM pms_product 
WHERE delete_status = 0 AND publish_status = 1 
ORDER BY id LIMIT 99990, 10;

在這里插入圖片描述

? 問題分析:

字段說明
type=index說明是走了索引,但是全索引掃描(index scan),相當于掃描整張表的索引部分。
key=PRIMARY表示使用的是主鍵索引(id)。
rows=100010MySQL 預估會掃描大約 10 萬行來定位 LIMIT 起始位置。
Extra=Using where表示 WHERE 條件在過濾過程中才判斷,并沒有用到復合索引來提前過濾。

?? 這意味著:

  • LIMIT 100000, 10 會導致 MySQL 掃描超過 10 萬條記錄,性能非常差。
  • WHERE 條件沒有使用到合適的索引(possible_keys 為 NULL)。

? 性能優化建議
1. 避免深分頁 —— 改用“基于游標”方式
例如前端傳入上一次返回結果的 last_id,實現類似“加載更多”:


SELECT * FROM pms_product 
WHERE delete_status = 0 AND publish_status = 1 AND id > 上一次最大 id
ORDER BY id
LIMIT 10;

優點:

  • 避免 offset,性能線性增長
  • 可以用覆蓋索引,避免回表
  • 建立合理的聯合索引
    如分頁條件為:

WHERE delete_status = 0 AND publish_status = 1 ORDER BY id

建議加:


CREATE INDEX idx_status_id 
ON pms_product(delete_status, publish_status, id);

這樣可以走索引,減少掃描行數。

3. 考慮分頁緩存
如果某些頁經常訪問,可以考慮將分頁結果緩存到 Redis,提升響應速度。

📝 總結

深分頁是一種常見但代價昂貴的分頁方式,特別在數據量大、頁碼大的時候:

  • offset 會嚴重拖慢查詢
  • 即使不使用 count(),深分頁依然很慢
  • 優化建議包括:改游標分頁、加索引、用緩存等

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

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

相關文章

LeetCode——1957. 刪除字符使字符串變好

通過萬歲!!! 題目:給你一個字符串,然后讓你刪除幾個字符串,讓他變成好串,好串的定義就是不要出現連續的3個一樣的字符。思路:首先就是要遍歷字符串。我們將要返回的字符串定義為ret&…

Aerospike與Redis深度對比:從架構到性能的全方位解析

在高性能鍵值存儲領域,Aerospike與Redis是兩款備受關注的產品。Redis以其極致的單機性能和豐富的數據結構成為主流選擇,而Aerospike則憑借分布式原生設計和混合存儲架構在大規模場景中嶄露頭角。本文將從架構設計、數據模型、性能表現、擴展性等核心維度…

Linux命令速查手冊

一、命令格式與輔助工具類別符號/命令示例說明基本格式commandls -a /home命令 選項 參數管道符ls -lless重定向>df -h > disk_usage.txt覆蓋寫入文件>>echo "New" >> notes.txt追加寫入文件2>ls non_exist 2> error.txt錯誤輸出重定向快捷…

net-snmp添加自定義mib樹

首先我們把前面mib2c生成的文件修改 下面重新做了個簡單點的MIB樹 -- -- -- MIB generated by MG-SOFT Visual MIB Builder Version 6.0 Build 88 -- Saturday, July 26, 2025 at 09:24:54 --ARHANGELSK-GLOBAL-REG DEFINITIONS :: BEGINIMPORTSenterprises, OBJECT-TYPE, M…

【動態規劃-斐波那契數列模型】理解動態規劃:斐波那契數列的遞推模型

算法相關知識點可以通過點擊以下鏈接進行學習一起加油!動態規劃是一種解決最優化問題的強大技術,通過將問題分解為子問題并逐步求解來實現高效計算。斐波那契數列是動態規劃中經典的應用之一,其遞推關系非常適合用動態規劃進行優化。通過動態…

微信小程序 自定義帶圖片彈窗

1. 微信小程序 自定義帶圖片彈窗1.1. 實現思路使用官方組件實現圖片模態彈窗。首先找到官方文檔:?顯示模態彈窗的API wx.showModal(OBJECT)wx.showModal參數介紹發現并沒有設置圖片的參數,但是這是一個API,但是組件呢?我并沒有在…

私有化大模型架構解決方案構建指南

內容概要本指南旨在為企業提供私有化大模型架構解決方案的全面構建路徑,幫助其在保障數據隱私的同時提升業務效率。我們將系統解析關鍵環節,包括安全部署策略設計、模型訓練核心技術、持續優化機制構建以及知識管理實踐路徑。此外,指南還涵蓋…

面試150 查找和最小的K對數字

思路1 超時法:通過兩個循環記錄三元組[num1,num2,num1num2]然后通過num1num2從小到大進行排序,然后返回前K個對數中的前兩個數即可。 class Solution:def kSmallestPairs(self, nums1: List[int], nums2: List[int], k: int) -> List[List[int]]:if n…

vscode目錄,右鍵菜單加入用VSCode打開文件和文件夾(快速解決)(含刪除)(腳本)

1.創建文本文件 在桌面右鍵單擊,選擇“新建” > “文本文檔”,將其命名為“vscode.txt”2.復制代碼內容3.修改文件擴展名 右鍵單擊“vscode.txt”文件,選擇“重命名”,將文件擴展名從.txt改為.reg,使其成為“vscode…

Chart.js 柱形圖詳解

Chart.js 柱形圖詳解 引言 在數據可視化領域,柱形圖是一種非常常見的圖表類型,它能夠直觀地展示不同類別或組的數據之間的比較。Chart.js 是一個基于 HTML5 Canvas 的開源庫,它提供了一系列的圖表繪制功能,其中包括柱形圖。本文將…

沉浸式文旅新玩法-基于4D GS技術的真人數字人賦能VR體驗升級

線下沉浸式劇場與 LBE VR 相結合,會碰撞出什么樣的火花?本次 PICO 視頻、東方演藝集團與火山引擎一起,將沉浸式演出《只此周莊》的部分場景復刻到了 VR 世界,讓用戶在虛擬的古代周莊夜市里,體驗了古老的故事以及精彩紛…

C程序內存布局詳解

C程序內存布局詳解 1. 內存布局概述 C程序在內存中分為以下幾個主要區域(從低地址到高地址): 代碼段(.text)只讀數據段(.rodata)初始化數據段(.data)未初始化數據段&…

新手向:Git下載全攻略

Git 的安裝與重要性在現代軟件開發中,版本控制是必不可少的工具,而 Git 是目前最流行的分布式版本控制系統。無論是個人開發者還是大型團隊,Git 都能高效管理代碼變更,確保項目歷史清晰可追溯。安裝 Git 是開發者入門的第一步&…

linux中如何清除history命令

寫在前面 使用ssh遠程連接客戶端連接上linux后操作的命令多了,有時候需要清除對應的歷史命令記錄,可以通過下面幾種方式實現。第一種方法 通過修改.bash_history文件 這是最簡單直接的方法,但是只會影響當前用戶的歷史記錄。執行以下命令即可…

PHP插件開發中的一個錯誤:JSON直接輸出導致網站首頁異常

問題描述 最近在使用步數統計插件&#xff08;WeFootStep&#xff09;時&#xff0c;發現網站首頁完全變成了一段JSON數據&#xff0c;而不是正常的HTML頁面。具體表現為首頁顯示如下內容&#xff1a; {"results":"<li><a href\"https:\/\/blog…

落霞歸雁的思維框架:十大經典思維工具的源頭活水

在當今復雜多變的世界中&#xff0c;思維框架成為了解決問題、優化決策和提升效率的重要工具。提到思維框架&#xff0c;人們往往會想到那些被廣泛認可和應用的十大經典思維工具&#xff1a;金字塔原理、黃金圈法則、5W1H分析法、SWOT分析、SCQA模型、STAR法則、PDCA循環、六頂…

spring Could 高頻面試題

一、基礎概念Spring Cloud 的核心組件有哪些&#xff1f; 答案&#xff1a;Eureka/Nacos&#xff08;服務注冊發現&#xff09;、Ribbon/LoadBalancer&#xff08;負載均衡&#xff09;、Feign/OpenFeign&#xff08;聲明式HTTP客戶端&#xff09;、Hystrix/Sentinel&#xff0…

從零開始的云計算生活——番外6,使用zabbix對中間件監控

目錄 一.網絡設備監控 1、GNS模擬器的使用 創建路由 創建交換機 2.構建網絡 3.添加Cisco路由器的監控 二.中間件監控 1、MySQL數據庫監控 1.1、拷貝自定義的監控腳本到指定目錄 1.2、添加監控用戶 1.3、重啟zabbix-agent服務 1.4、在zabbix-server服務端測試數據 1…

haproxy七層均衡

一.haproxy的安裝和服務信息1.1實驗環境ip實驗設備172.25.254.100haproxy172.25.254.10RS1172.25.254.20RS2172.25.254.111client1.2軟件安裝及配置haproxy主機上配置#下載#進入此文件進行編輯#關閉防火墻RS1主機上配置#下載#生成默認文件#重啟#關閉防火墻RS2主機上配置#下載#生…

分類預測 | MATLAB實現CPO-SVM冠豪豬算法優化支持向量機分類預測

分類預測 | MATLAB實現CPO-SVM冠豪豬算法優化支持向量機分類預測 目錄 分類預測 | MATLAB實現CPO-SVM冠豪豬算法優化支持向量機分類預測 分類效果 基本介紹 算法步驟 參數設定 運行環境 應用場景 程序設計 參考資料 分類效果 基本介紹 該MATLAB代碼實現了基于冠豪豬優化算法(…