資料排序需求有時無可避免,以前SQL Server2014使用row by row來處理資料排序,
這種方式對小資料表來說可能沒啥效能影響,但如果對大資料表來說可不得不在意效能,
那麼SQL Server 2016要使用什麼方法來改善效能呢?
我們知道每一版SQL Server QO(Query Optimizer)都會增強,
SQL Server 2016當然也不例外,排序效能改善前提是排序需使用columnstore indexes,
這時資料排序預設將使用批次模式而非資料列模式(有時也會使用資料列模式),
雖然絕大多數情況批次模式可改善效能,但某些複雜情況(如平行處理)卻會帶來一些麻煩,
現在我來簡單驗證一下,資料排序使用批次模式所帶來的效能改善。
select * from SalesOrderDetail
where linetotal>6000
order by orderqty
使用資料列模式排序,經過時間204 ms;logical read:1500。
ALTER TABLE dbo.SalesOrderDetail DROP CONSTRAINT PK_SalesOrderDetail
--建立clustered columnstore Index
create clustered columnstore Index PK_SalesOrderDetail
on dbo.SalesOrderDetail;
--再次執行相同查詢
DBCC DROPCLEANBUFFERS();
select * from SalesOrderDetail
where linetotal>6000
order by orderqty
使用批次模式排序,經過時間150 ms;logical read:0,但記憶體授權會增加。
Note:從SQL2016開始,只要SQL Server有足夠記憶體,
如遇排序使用tempdb處理的話,可使用Trace Flag 9389來啟用批次模式進行排序,
這樣即可避免額外I/O。
Trace Flag 9347
我前面有提到,遇到某些情況,批次模式可能會造成麻煩,
所以SQL Server 2016提供Trace Flag 9347關閉使用批次模式進行排序處理。
select * from SalesOrderDetail
where linetotal>6000
order by orderqty
OPTION (QUERYTRACEON 9347)
Note:複雜平行處理可透過Trace Flag 9358關閉批次模式排序。
TOP N Sort
Top n sort和一般sort不同我想大家都知道,
所以Trace Flag 9349主要是針對TOP N sort來關閉批次模式排序。
select top 90 * from SalesOrderDetail
where linetotal>10000
order by orderqty
使用批次模式排序資料,整體記憶體授權:66208kb,排序成本10%。
T9349關閉批次模式,再次執行相同查詢比較
DBCC DROPCLEANBUFFERS();
select top 90 * from SalesOrderDetail
where linetotal>10000
order by orderqty
OPTION (QUERYTRACEON 9349)
使用資料列模式排序資料,整體記憶體授權大幅降低為1024kb,但排序成本卻成長為22%。
Enjoy SQL Server 2016
參考
[SQL SERVER][Denali] Columnstore Index 執行模式 (Row VS Batch)
FIX: Can't force Row Mode sort by using session or query level trace flag 9347 in SQL Server 2016