[SQL SERVER][Denali] TSQL 新特性(上)

[SQL SERVER][Denali] TSQL 新特性(上)

這篇我們來看看 Denali 在TSQL方面所帶來的新特性。

 

1.Offset and Fetch First/Next(分頁操作改善)

SQL2005/2008 我想大家都會透過row_number function 來達到分頁效果,

而在 Denali 你可以有更好的選擇,使用 Offset and Fetch First/Next 你將感受到分頁操作就是這麼簡單且更有效率。

 

假設今天我希望每頁顯示15筆資料,在 Denali 實現分頁真的再簡單不過了,同時我也會簡單測試兩者效能差異。

SQL2011 分頁操作

set statistics io on;
set statistics time on;
declare @currentpage int,@pagecount int
set @currentpage=0 --現在頁數(0=第一頁)
set @pagecount=15--每頁顯示筆數
select * from Production.TransactionHistory t1
order by t1.TransactionID
Offset @currentpage*@pagecount rows --第一筆 rownum
fetch next @pagecount rows only --從第一筆 rownum 往下取得總筆數

 

 

 

 

statistics io/time(經過時間=65 ms)

image

 

執行計畫(總成本=0.0039108)

image

 

SQL2005/2008 分頁操作

set statistics io on;
set statistics time on;
declare @currentpage int,@pagecount int
set @currentpage=0 --現在頁數(0=第一頁)
set @pagecount=15--每頁顯示筆數
;with mycte as 
(
select row_number() over (order by TransactionID) 'rownum',*
from Production.TransactionHistory 
)
select * from mycte
where rownum >(@currentpage*@pagecount) and rownum<=(@currentpage*@pagecount)+@pagecount

 

statistics io/time(經過時間=70 ms)

 

 

 

image

 

執行計畫(總成本=0.0040088)

image

和SQL2011 執行計畫比較可說複雜多了。

 

一起比較兩者執行計畫成本(SQL2011執行計畫較優於SQL2005/2008)

image

 

效能比較結果表

image

 

2.WITH RESULT SETS

(注意:With Result Sets不支援 Insert …. Exec 陳述句)

以前我們透過 SP(store procedure)想要取得查詢結果集,通常會將結果塞入 TempTable 或 TVP..等,

然後再查詢取得相關結果集,但 Denali 不需要你這麼麻煩(不需要使用 TempTable或TVP..等),

我們可以直接利用 With Result Sets 就能達到目的,且也能減少整體時間,同時更能在執行過程中更改欄位名稱或資料型別。

 

建立SP

create proc dbo.mysp(@tid int)
as
select TransactionID,ProductID,TransactionType,ModifiedDate
from Production.TransactionHistory
where TransactionID=@tid

 

 

 

執行SP

exec dbo.mysp 100004
with result sets
(
(
TransactionID int,
ProductID int,
TransactionType varchar(10),--更改資料型別
MyModifiedDate datetime --更改欄位名稱
)
)

 

 

 

image

 

3.Rows and Range:允許更改分區中的開始位置和結束位置

注意:

1.並非所有function 都支援 rows and range

2.使用 rows and range必須指定 order by

3.有指定 order by但未使用rows and range,則預設為 range between undounded preceding and current rows。

 

 

假設今天我們需要計算累加值

原始資料

image

 

SQL2011作法

declare @starttime time(7),@endtime time(7),@elaspedtime numeric(20,7);
set @starttime=GETDATE() 
select c1,c2, sum(c2) over (order by c1
range unbounded preceding) as '累加量'
from dbo.mysales 
set @endtime=GETDATE(); 
set @elaspedtime = convert(integer, datediff(ms, @starttime, @endtime));
select @elaspedtime as '花費時間(ms)' 

 

 

 

 

經過時間=50 ms

image

 

執行計畫(總成本=0.0147154)

image

 

SQL2005/2008

做法可以參考[SQL SERVER][TSQL]如何計算累加值

 

經過時間=63 ms

image

 

執行計畫(總成本=0.0132996+0.0132842+0.0032831=0.0298669)

image

 

一起比較兩者執行計畫成本(SQL2011執行計畫較優於SQL2005/2008)

--2011
select c1,c2, sum(c2) over (order by c1
range unbounded preceding) as '累加量'
from dbo.mysales 
--2005/2008
--結果表
declare @result table
(
c1 varchar(10),
c2 int,
total int default(0)
)
insert into @result select *,0 from dbo.mysales
declare @total int
set @total=0
update @result
--設定變數與資料行相同的值
set @total = total = @total + c2
--結果 
select t1.c1,t1.c2,t1.total as '累加量'  
from @result t1 

 

 

 

image

 

效能比較結果表

image

 

設定開始位置和結束位置五種方式

image

 

select c1,c2,sum(c2) over (order by c1
range unbounded preceding) as '累加量1',
sum(c2) over (order by c1
range between unbounded preceding AND unbounded following) as '累加量2',
sum(c2) over (order by c1
rows between current row and 1 following ) as '累加量3',
sum(c2) over (order by c1
rows 1 preceding ) as '累加量4',
sum(c2) over (order by c1
rows between 1 preceding and 3 following  ) as '累加量5'
from dbo.mysales

 

 

 

image

 

當然Rows and Range 應用不只這些,其餘應用大家有興趣可自行測試看看。