我正在用SQL Server進行分頁,我想通過將結果的總數作爲部分結果集的一部分來避免重複,而不是獲取該結果集,然後執行單獨的查詢以獲取計數。但是,麻煩在於,它似乎在增加執行時間。例如,如果我請與SET STATISTICS TIME ON
,這樣的:在CTE內部使用COUNT()比在CTE之外更昂貴嗎?
WITH PagedResults AS (
SELECT
ROW_NUMBER() OVER (ORDER BY AggregateId ASC) AS RowNumber,
COUNT(PK_MatrixItemId) OVER() AS TotalRowCount,
*
FROM [MyTable] myTbl WITH(NOLOCK)
)
SELECT * FROM PagedResults
WHERE RowNumber BETWEEN 3 AND 4810
...或者這個(其執行計劃是相同的):
SELECT * FROM (
SELECT TOP (4813)
ROW_NUMBER() OVER (ORDER BY AggregateId ASC) AS RowNumber,
COUNT(PK_MatrixItemId) OVER() AS TotalRowCount,
*
FROM [MyTable] myTbl WITH(NOLOCK)
) PagedResults
WHERE PagedResults.RowNumber BETWEEN 3 AND 4810
...似乎是一個平均的CPU時間(全查詢的1.5〜2倍加起來)不亞於此:
SELECT * FROM (
SELECT TOP (4813)
ROW_NUMBER() OVER (ORDER BY AggregateId ASC) AS RowNumber,
*
FROM [MyTable] myTbl WITH(NOLOCK)
) PagedResults
WHERE PagedResults.RowNumber BETWEEN 3 AND 4810
SELECT COUNT(*) FROM [MyTable] myTbl WITH(NOLOCK)
很顯然,我寧願用前者比後者,因爲後者冗餘重複FROM
條款(和W如果有的話,可以重複任何WHERE
條款),但是它的執行時間要好得多,我真的必須使用它。有什麼辦法可以讓我減少前者的執行時間?
你從執行計劃中得到了什麼?理解你的選擇並給出一些關於解釋的暗示應該是有用的。 – Paolo 2014-10-16 09:59:26
這很難說,因爲執行計劃是非常不同的,但據我所見,前者的執行計劃包含一個「嵌套循環」階段,將count列連接到其餘的,這有一個很大的開銷。 – Jez 2014-10-16 10:08:12