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

存儲過程分頁優化實戰:從百萬級數據到高效查詢的完整指南

     編輯:關於SqlServer

為什麼需要存儲過程分頁?

面對海量數據時,傳統查詢語句往往力不從心。即使數據庫配置優化、表結構設計精心,一旦結果集超過總數據量的 40%,數據庫層面的優化便難以奏效。此時分頁成為必然選擇:指定頁面大小(PageSize)與當前頁索引(CurrentPage),即可從百萬級數據中精準提取所需記錄。例如每頁 50 條,從 100 萬記錄中查詢 50 條,比例極小,不僅大幅降低網絡傳輸量,更能顯著減少內存開銷、頁面刷新時間與用戶等待。

核心場景:連續表與不連續表

實戰中將表分為兩類:

  • 連續表:擁有唯一自增索引且無斷號(如未被刪除過記錄)。
  • 不連續表:無唯一自增索引,或因刪除操作導致索引不連續。

連續表分頁:ID 篩選法(極致性能)

CREATE PROCEDURE SelectProduct
  @PageSize int, @CurrentPage int, @TotalPage int output
BEGIN
  EXEC('SELECT TOP ' + @PageSize + ' * FROM Product WHERE ProductId > (' + @PageSize + '*' + @CurrentPage + ')')
  SELECT @TotalPage = COUNT(*) / @PageSize FROM Product
END

測試數據(72 萬記錄,每頁 50 條):

頁碼執行時間
11 ms
1002 ms
10004 ms
50009 ms
1000013 ms
1400016 ms

百萬級數據均在 0.1 秒內完成,但隨頁碼增大呈現緩慢增長趨勢。

不連續表分頁:三大方案深度對比

模擬斷號:DELETE FROM Product WHERE ProductId % 24 = 0(刪除 3 萬餘條)。

方案一:重建自增索引(DBCC CHECKIDENT)

適用於無外鍵依賴的表,效率最高,但會破壞關聯完整性,謹慎使用。

方案二:臨時表分頁

局部臨時表(#Tmp)

每次查詢創建、銷毀,插入數據佔 90%+ 耗時。適用於小數據量(<10 萬)。

全局臨時表(##Tmp)

預先構建,查詢極快(70 萬記錄僅 86 ms),但需定時維護同步,維護成本高。

方案三:ROW_NUMBER() 窗口函數(SQL Server 2005+)

SELECT * FROM (
  SELECT *, ROW_NUMBER() OVER (ORDER BY ProductId) AS ROWNUM FROM Product
) AS t WHERE ROWNUM BETWEEN @BeginId AND @EndId

測試對比:

記錄數局部臨時表全局臨時表ROW_NUMBER()
10,000198 ms10 ms210 ms
100,000669 ms27 ms150 ms
700,0005,543 ms86 ms86 ms

核心結論

分頁本質是「編號重建」:連續表直接用 ID;不連續表通過臨時表或 ROW_NUMBER() 重建連續編號。小數據量用局部臨時表,大數據量首選 ROW_NUMBER()(無維護成本)或全局臨時表(極致性能,接受維護成本)。


註:數據為實測參考,不同環境差異較大。轉載請註明出處:https://www.cnblogs.com/4inwork

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