面對海量數據時,傳統查詢語句往往力不從心。即使數據庫配置優化、表結構設計精心,一旦結果集超過總數據量的 40%,數據庫層面的優化便難以奏效。此時分頁成為必然選擇:指定頁面大小(PageSize)與當前頁索引(CurrentPage),即可從百萬級數據中精準提取所需記錄。例如每頁 50 條,從 100 萬記錄中查詢 50 條,比例極小,不僅大幅降低網絡傳輸量,更能顯著減少內存開銷、頁面刷新時間與用戶等待。
實戰中將表分為兩類:
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 條):
| 頁碼 | 執行時間 |
|---|---|
| 1 | 1 ms |
| 100 | 2 ms |
| 1000 | 4 ms |
| 5000 | 9 ms |
| 10000 | 13 ms |
| 14000 | 16 ms |
百萬級數據均在 0.1 秒內完成,但隨頁碼增大呈現緩慢增長趨勢。
模擬斷號:DELETE FROM Product WHERE ProductId % 24 = 0(刪除 3 萬餘條)。
適用於無外鍵依賴的表,效率最高,但會破壞關聯完整性,謹慎使用。
每次查詢創建、銷毀,插入數據佔 90%+ 耗時。適用於小數據量(<10 萬)。
預先構建,查詢極快(70 萬記錄僅 86 ms),但需定時維護同步,維護成本高。
SELECT * FROM (
SELECT *, ROW_NUMBER() OVER (ORDER BY ProductId) AS ROWNUM FROM Product
) AS t WHERE ROWNUM BETWEEN @BeginId AND @EndId
測試對比:
| 記錄數 | 局部臨時表 | 全局臨時表 | ROW_NUMBER() |
|---|---|---|---|
| 10,000 | 198 ms | 10 ms | 210 ms |
| 100,000 | 669 ms | 27 ms | 150 ms |
| 700,000 | 5,543 ms | 86 ms | 86 ms |
分頁本質是「編號重建」:連續表直接用 ID;不連續表通過臨時表或 ROW_NUMBER() 重建連續編號。小數據量用局部臨時表,大數據量首選 ROW_NUMBER()(無維護成本)或全局臨時表(極致性能,接受維護成本)。
註:數據為實測參考,不同環境差異較大。轉載請註明出處:https://www.cnblogs.com/4inwork