在SQL Server中,針對複雜查詢使用TOP子句可能會出現對性能的影響,這種影響多是好的影響,也多是壞的影響,針對不一樣的狀況有不一樣的可能性。算法
關係數據庫中SQL語句只是一個抽象的概念,不包含任何實現。不少元數據都會影響執行計劃的生成,SQL語句自己並不做爲生成執行計劃所參考的元數據(提示除外),但TOP關鍵字倒是直接影響執行計劃的一個關鍵字,所以在某些狀況下使用TOP會致使性能受到影響,下面咱們來看集中不一樣的狀況。數據庫
對於單表查詢(這裏的所說的單表指的是不包含視圖、表值函數的物理單表)來講,存在TOP基本不會對性能產生影響,若是在SQL Server中加入了TOP,那麼TOP自己能夠看做是一個查詢提示,意味着告訴優化器「返回結果只有N行」。咱們看一個簡單的例子,如圖1所示:app
圖1.指定TOP關鍵字的單表執行計劃函數
由圖1執行計劃對比能夠看出,對於有索引支撐的單表查詢來講,使用TOP子句每每能夠提高性能,此時TOP N的行數的N則提示查詢優化器該查詢返回N行,而不是使用統計信息中的數據分佈,此時TOP N對於查詢優化器來講是合理的。oop
但有些時候Grant Memory(每次執行計劃生成時會預估所需的內存,若是預估內存小於執行內存,則會spill to tempdb,對性能產生很是大的影響,因爲每個版本預估內存的公式變化極大,所以不在此詳細解釋了)不許會產生很是高的性能影響。在開始談這點,以前,咱們先談兩個操做符:性能
Sort操做符是很是通用的排序操做符,在執行計劃中可能會出如今多個地方,好比Merge Join以前,因爲Order By致使的等。該算法很是通用,能夠對很是大的結果集進行排序,該操做符是阻塞式(意味着排序結束以前數據沒法流動到下一個操做符),而且須要大量內存和CPU資源。該操做符還有一個問題是當Grant Memory不足時,須要TempDB輔助完成排序,所以有極大的性能開銷。測試
TOP N Sort是適應小場景,專門針對少許查詢的排序算法。對於只選擇幾條數據來講,對於整個結果集進行排序成本過於高昂,所以TOP N的算法是首先取第一條數據,與其餘數據進行對比,看是否最大(或最小),再取第二條數據對比,依次類推,直到找到前N條數據。該算法若是行數較小,則相比SORT操做符性能提高明顯,但若是N值過大,則因爲下述緣由該算法不合適:優化
1.該算法不支持spill to tempdb,致使沒法承載太大的結果集。spa
2.該算法須要遍歷N次,若是N過大,則成本太高。3d
對於SQL Server來講,這個N是否過大的閾值是100。下面咱們來看一個例子,測試數據和代碼如代碼清單1所示。
CREATE TABLE TestTop
(id INT,sortkey INT,SOMEvalue CHAR(1000))
DECLARE @i INT =1
WHILE @i<300000
BEGIN
INSERT INTO TestTop VALUES(@i,@i,'a')
SET @i=@i+1
END
CREATE CLUSTERED INDEX PK_id ON TestTop(id)
--test 1
SELECT TOP(100) * FROM TestTop
ORDER BY sortkey
--test 2
SELECT TOP(101) * FROM TestTop
ORDER BY sortkey
代碼清單1.測試數據與測試代碼
第一個測試爲TOP 100,正好使用TOP N Sort的算法,第二個測試爲TOP 101,只能使用普通Sort的算法,如圖2所示。
圖2.TOP 101的SORT須要更多內存,從而致使內存授予不足spill to tempdb
咱們再來看執行時間,因爲spill to tempdb的存在,那麼執行時間如圖3所示。
圖3.相差很是大的執行時間
從圖3能夠看出,執行時間相差很是大。
所以對於TOP的使用來講,儘可能使用TOP 100之內的數值。
因爲TOP語句帶有對優化器基數估計的提示功能,所以多表查詢時在極端狀況下可能致使行數低估從而影響性能。
好比下面如圖4的示例查詢
圖4.使用TOP 1的表接連查詢
在這種狀況下,因爲TOP1的存在使得查詢優化器使用1做爲估計行數,與實際的行數差別巨大,所以對於這種狀況,使用TOP反而可能致使成本更高(雖然咱們看到圖4中估計的是0%對比100%,但實際差別巨大),更高的緣由不只僅是優化器估計爲1,由於Loop Join只要發現1條就能夠馬上結束,但上面例子中因爲過濾條件選擇性太低,致使找到第一條數據的隨機查找過多(loop join內表循環是隨機IO),成本如圖5所示。
圖5.使用TOP反而致使性能降低
根本緣由是因爲估計行數只有1行,大部分狀況下這一行
對於上面這種狀況來講,咱們一般能夠有下面集中解決辦法:
1.使用提示,因爲咱們知道這是因爲實際行數遠大於估計行數致使,所以咱們能夠嘗試使用hash join,forcescan等提示。
2.增長where條件,使得返回行數具備更高的選擇性。
3.不使用TOP1,而使用TOP 10以上的數字,讓估計行數變大,好比圖5中的查詢咱們由TOP1 變爲TOP10,那麼執行計劃則變爲如圖6所示。
圖6.TOP 10的執行計劃
這是因爲當行數少時,LOOP JOIN能夠更快返回有限的行數,至關於對錶加了FAST N提示,但行數增多時,優化器更傾向使用MERGE或者HASH完成操做,在上面返回行極多(選擇性低)的極端狀況下,會擁有更好的性能,結果如圖7所示。
圖7.特殊狀況下TOP10相比TOP1有更好性能。
所以結合單表的例子,推薦使用TOP關鍵字時,數字在10到100之間。
本文介紹了TOP關鍵字在單表和多表條件下可能對執行計劃產生的影響,進而影響了查詢計劃。TOP影響執行計劃主要是下面兩個方面:
所以在特殊狀況下調優TOP語句時,能夠根據實際狀況考慮本文的建議。