SQL SERVER2012在ORDER BY 子句中加入了新元素offset,允許用戶在排序完成的結果集中自定義輸出行范圍,大大簡化了分頁SQL的書寫方式和效率。以下是與以前的兩種分頁方式的簡單對比
use master go set nocount on go set showplan_text on go
--2012的OFFSET分頁方式 select number from spt_values where type='p' order by number offset 10 rows fetch next 5 rows only; go
--2005的ROW_NUMBER分頁方式 select number from ( select number,row_number() over(order by number) as num from spt_values where type='p' ) t where num between 11 and 15 order by number asc go
--2000的TOP分頁方式 select number from ( select top 5 number from ( select top 15 number from spt_values where type='p' order by number asc ) t order by number desc ) t order by number asc go set showplan_text off go /* StmtText ---------------------------------------------------------------------------------------------------------- select number from spt_values where type='p' order by number offset 10 rows fetch next 5 rows only; StmtText -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |--Top(OFFSET EXPRESSION:((10)),TOP EXPRESSION:((5))) |--Index Scan(OBJECT:([mssqlsystemresource].[sys].[spt_values].[ix2_spt_values_nu_nc]), WHERE:(CONVERT(nchar(3),[mssqlsystemresource].[sys].[spt_values].[type],0)=N'p') ORDERED FORWARD) StmtText --------------------------------------------------------------------------------------------------------------------------------------------------------------------- select number from ( select number,row_number() over(order by number) as num from spt_values where type='p' ) t where num between 11 and 15 order by number asc StmtText ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |--Sort(ORDER BY:([mssqlsystemresource].[sys].[spt_values].[number] ASC)) |--Filter(WHERE:([Expr1005]>=(11) AND [Expr1005]<=(15))) |--Top(TOP EXPRESSION:(CASE WHEN (15) IS NULL OR (15)<(0) THEN (0) ELSE (15) END)) |--Sequence Project(DEFINE:([Expr1005]=row_number)) |--Segment |--Index Scan(OBJECT:([mssqlsystemresource].[sys].[spt_values].[ix2_spt_values_nu_nc]), WHERE:(CONVERT(nchar(3),[mssqlsystemresource].[sys].[spt_values].[type],0)=N'p') ORDERED FORWARD) StmtText ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- select number from ( select top 5 number from ( select top 15 number from spt_values where type='p' order by number asc ) t order by number desc ) t order by number asc StmtText ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |--Sort(ORDER BY:([mssqlsystemresource].[sys].[spt_values].[number] ASC)) |--Sort(TOP 5, ORDER BY:([mssqlsystemresource].[sys].[spt_values].[number] DESC)) |--Top(TOP EXPRESSION:((15))) |--Index Scan(OBJECT:([mssqlsystemresource].[sys].[spt_values].[ix2_spt_values_nu_nc]), WHERE:(CONVERT(nchar(3),[mssqlsystemresource].[sys].[spt_values].[type],0)=N'p') ORDERED FORWARD) */
從查詢計划來看,2012的查詢計划中,offset直接操作了top迭代器,分頁計划十分簡單,看起來也比后兩種簡單明了。
而在系統預估的查詢開銷中,OFFSET占9%,ROW_NUMBER占45%,TOP占47%(加起來101% -_-||),OFFSET占了絕對的優勢。
在2008的更新中,我最喜歡的是MERGE,2012中就是OFFSET了。