[SQL SERVER]SQL2016-排序效能改善

資料排序需求有時無可避免,以前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]你不知道的Trace Flag

[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

Adds trace flag 9358 to disable batch mode sort operations in a complex parallel query in SQL Server 2016