標籤:com 查詢 img 除了 core product 資料 -- where
原文: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 QUERYSELECT ProductIDFROM ( SELECT ProductID, ROW_NUMBER() OVER (ORDER BY ProductID) AS RN FROM Production.Product ) AS TWHERE T.RN <= 100GO-- TOP N QUERYSELECT TOP 100 ProductIDFROM Production.ProductORDER BY ProductIDGO
如所知,對於這兩個查詢計劃的成本是一樣的,都為50%。 如果我們要檢查在兩個叢集索引掃描操作符中讀取的估計行數,那麼我們會注意到兩者都顯示相同的值,即100。可以說叢集索引掃描的估計和實際行數是相同的都是100,如下。
是不是就以此說明二者效能是一樣的呢?稍等片刻,接下來我們將查詢基數再設定大一點看看,比如1000而不再是100,如下:
DBCC DROPCLEANBUFFERS()DBCC FREEPROCCACHE()GOSET STATISTICS IO ONSET STATISTICS TIME ON--ROW_NUMBER QUERYSELECT ProductIDFROM ( SELECT ProductID, ROW_NUMBER() OVER (ORDER BY ProductID) AS RN FROM Production.Product ) AS TWHERE T.RN <= 1000GO-- TOP N QUERYSELECT TOP 1000 ProductIDFROM Production.ProductORDER BY ProductIDGO
從如上可以看出,使用ROW_NUMBER進行查詢的速度要明顯快於TOP N,即29%和71%。 但是,我們還需要在等一下,因為我們在這裡看到的成本只是估計成本。 如果操作的估算不準確,那麼查詢計劃估算成本也將不準確。 接下來我們檢查兩個計劃中的叢集索引掃描的屬性:
我們可以看到,使用ROW_NUMBER查詢的估計行數為100,而實際數量為504,查詢計劃的估計成本是基於估計的行數所計算得來,即100。我們還是不能夠相信估計的規劃成本。 我們再來看看統計資料:
經過上面的統計,我們可以根據統計資料而做出最終決定,而不是比較執行計畫的估計成本。TOP N的查詢效能優於ROW_NUMBER。
總結
從上比較TOP N和ROW_NUMBER的查詢得知,查詢計劃所得到的成本並不是判斷效能的最終依據,只是基礎性的判斷,我們最終還得集合IO和TIME等來綜合判斷效能差異。
SQL Server-聚焦ROW_NUMBER VS TOP N效能