SQL Server-聚焦ROW_NUMBER VS TOP N性能


前言

抱歉各位,從八月份開始一直在着手寫EntityFramework 6.x和EntityFramework Core 2.0的書籍寫作,所以最近一直遺漏了對博客的管理,后面會着手於寫SQL Server、EntityFramework Core和.NET Core方面的博客。我們知道如果需要查詢前N行數據,除了可以利用TOP N進行查詢外,同樣也可以利用ROW_NUMBER來達到同樣的效果,那么二者使用哪個性能會更好呢?下面我們來比較下。

ROW_NUMBER VS TOP N

我們利用AdventureWorks2012示例庫中的Production.Product表來進行演示,如下:

DBCC DROPCLEANBUFFERS()
DBCC FREEPROCCACHE()
GO

--ROW_NUMBER QUERY
SELECT ProductID
FROM (
    SELECT ProductID, ROW_NUMBER() OVER (ORDER BY ProductID) AS RN
    FROM Production.Product
    ) AS T
WHERE T.RN <= 100
GO

-- TOP N QUERY
SELECT 
    TOP 100 ProductID
FROM Production.Product
ORDER BY ProductID
GO

如上圖所知,對於這兩個查詢計划的成本是一樣的,都為50%。 如果我們要檢查在兩個聚集索引掃描操作符中讀取的估計行數,那么我們會注意到兩者都顯示相同的值,即100。可以說聚集索引掃描的估計和實際行數是相同的都是100,如下。

 

是不是就以此說明二者性能是一樣的呢?稍等片刻,接下來我們將查詢基數再設置大一點看看,比如1000而不再是100,如下:

DBCC DROPCLEANBUFFERS()
DBCC FREEPROCCACHE()
GO
SET STATISTICS IO ON
SET STATISTICS TIME ON
--ROW_NUMBER QUERY
SELECT ProductID
FROM (
    SELECT ProductID, ROW_NUMBER() OVER (ORDER BY ProductID) AS RN
    FROM Production.Product
    ) AS T
WHERE T.RN <= 1000
GO

-- TOP N QUERY
SELECT 
    TOP 1000 ProductID
FROM Production.Product
ORDER BY ProductID
GO

從如上截圖可以看出,使用ROW_NUMBER進行查詢的速度要明顯快於TOP N,即29%和71%。 但是,我們還需要在等一下,因為我們在這里看到的成本只是估計成本。 如果操作的估算不准確,那么查詢計划估算成本也將不准確。 接下來我們檢查兩個計划中的聚集索引掃描的屬性:

 

我們可以看到,使用ROW_NUMBER查詢的估計行數為100,而實際數量為504,查詢計划的估計成本是基於估計的行數所計算得來,即100。我們還是不能夠相信估計的計划成本。 我們再來看看統計數據:

經過上面的統計,我們可以根據統計數據而做出最終決定,而不是比較執行計划的估計成本。TOP N的查詢性能優於ROW_NUMBER。 

總結

從上比較TOP N和ROW_NUMBER的查詢得知,查詢計划所得到的成本並不是判斷性能的最終依據,只是基礎性的判斷,我們最終還得集合IO和TIME等來綜合判斷性能差異。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM