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

SQL Server 分頁存儲程式兩種寫法效能比較與優化建議

     編輯:關於SqlServer

背景

在 SQL Server 2000 時代(無 `ROW_NUMBER()`、`OFFSET/FETCH`),分頁查詢是常見挑戰。作者測試 15,000~30,000 筆資料,發現有索引/鍵值時效能差異明顯。

寫法一:SET ROWCOUNT + 子查詢(推薦)

CREATE PROC sp_fixpage @pagesize INT, @destpage INT AS
SET NOCOUNT ON
DECLARE @id INT, @startid INT
SELECT @startid = (@destpage - 1) * @pagesize
SET ROWCOUNT @startid
SELECT @id = id FROM t_member  -- 略過前 N 筆,取得游標位置
SET ROWCOUNT @pagesize
SET NOCOUNT OFF
SELECT * FROM t_member WHERE id > @id ORDER BY id
GO

優點:語法簡潔、利用索引定位、無需臨時表/游標。
缺點:`SET ROWCOUNT` 不影響 `INSERT/UPDATE/DELETE`,未來版本將棄用。

寫法二:SCROLL GAME CURSOR + 臨時表(不推薦)

CREATE PROCEDURE sp_fixpage1 @pagesize INT, @destpage INT AS
SET NOCOUNT ON
CREATE TABLE #myTable ( ... 完整欄位定義 ... )
DECLARE @tempPos INT, @absPos INT, @nowID INT
SET @absPos = CASE WHEN @destpage > 1 THEN (@pagesize * (@destpage - 1) + 1) ELSE 1 END
DECLARE myCursor SCROLL CURSOR FOR SELECT [ID] FROM t_member ORDER BY id
OPEN myCursor
FETCH ABSOLUTE @absPos FROM myCursor INTO @nowID
WHILE (@@FETCH_STATUS = 0) AND (@tempPos <= @pagesize)
BEGIN
    INSERT INTO #myTable SELECT * FROM t_member WHERE [ID] = @nowID
    FETCH NEXT FROM myCursor INTO @nowID
    SET @tempPos = @tempPos + 1
END
CLOSE myCursor; DEALLOCATE myCursor
SELECT * FROM #myTable; DROP TABLE #myTable
GO

缺點:需定義完整臨時表結構、游標開銷大、程式碼冗長、維護困難。

效能測試結論

資料量寫法一寫法二
15,000 筆持平持平
20,000~30,000 筆明顯較快較慢

關鍵因素:資料表是否有鍵值與索引,對兩種寫法效能影響極大。

現代化建議(SQL Server 2012+)

SELECT * FROM t_member ORDER BY id
OFFSET (@pagesize * (@destpage - 1)) ROWS FETCH NEXT @pagesize ROWS ONLY

標準語法、最佳化器支援完善、可讀性最佳。

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