SQL Server2012 T-SQL對分頁的增強嘗試


簡介

    SQL Server 2012中在Order By子句之后新增了OFFSET和FETCH子句來限制輸出的行數從而達到了分頁效果。相比較SQL Server 2005/2008的ROW_Number函數而言,使用OFFSET和FETCH不僅僅是從語法角度更加簡單,並且擁有了更優的性能(看到很多人下過這個結論,但我測試有所偏差,暫且保留意見)。

    MSDN上對於OFFSET和FETCH的詳細描述可以在(http://msdn.microsoft.com/en-us/library/ms188385%28v=SQL.110%29.aspx)找到。

 

OFFSET和FETCH

    這兩個關鍵字在MSDN原型使用方式如代碼1所示。

ORDER BY order_by_expression
    [ COLLATE collation_name ] 
    [ ASC | DESC ] 
    [ ,...n ] 
[ <offset_fetch> ]


<offset_fetch> ::=
{ 
    OFFSET { integer_constant | offset_row_count_expression } { ROW | ROWS }
    [
      FETCH { FIRST | NEXT } {integer_constant | fetch_row_count_expression } { ROW | ROWS } ONLY
    ]
}

    代碼1.OFFSET和FETCH在MSDN的原型

 

    可以看到,OFFSET使用起來很簡單,首先在OFFSET之后指定從哪條記錄開始取。其中,取值的數可以是常量也可以是變量或者表達式。而Row和ROWS在這里是一個意思。

    然后通過FETCH關鍵字指定取多少條記錄。其中,FIRST和NEXT是同義詞,和前面的ROW和ROWS一樣,它們可以互相替換。同樣,這里取的記錄條數也可以是常量或者變量表達式。

 

    下面通過一個例子來看OFFSET和FETCH的簡單用法。首先創建測試數據,這里我就偷懶了,使用我上篇文章的測試數據,創建表后插入100萬條測試數據,這個表非常簡單,一個自增的id字段和一個int類型的data字段,創建表的語句我就不貼了,插入測試數據的代碼如圖1所示。

    4

     圖1.插入測試數據

 

    下面,我要取第500000到500100的數據,如圖2所示。

    1

    圖2.取50萬到500100之間的數據

 

     可以看到,使用OFFSET和FETCH關鍵字使分頁變得如此簡單。

 

OFFSET…FETCH分頁對性能的提升

    OFFSET和FETCH語句不僅僅是語法糖,還能帶來分頁效率上的提升。下面我們通過一個例子進行比較SQL Server 2012和SQL Server 2005/2008不同分頁方式的分頁效率。我們同樣取50萬到500100之間的數據,性能對比如圖3所示。

    2

     圖3.SQL Server 2012分頁和SQL Server 05/08之間分頁效率對比

 

     但是,查詢計划中我看到SQL Server2012中FETCH..NEXT卻十分損耗性能。這和前面的測試結果嚴重不符,如圖4所示。

    3

    圖4.兩種方式的執行計划

  

    通過對比掃描聚集索引這步,我發現對於估計執行行數存在嚴重偏差,如圖5所示。

    45

    圖5.存在偏差的執行計划

 

    上圖中,第一張圖片是使用OFFSET…FETCH進行分頁的。估計行數居然占到了500100,嚴重不符。這令我十分費解,暫時還沒有找出原因,求各路大神指導….

總結

    SQL Server 2012帶來的分頁效果十分強大,使得大大簡化在SQL Server下的分頁。對於性能的影響,由於出現了上述執行計划的偏差,暫且不下結論。待日后研究有了進展再來補上。


免責聲明!

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



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