2010年12月30日 星期四

UNION VS. UNION ALL 的效能

以前並沒有特別在意 UNION 與 UNION ALL 對於 T-SQL 效能的影響,直到最近 UNION 上萬筆資料後,才深深發現這小小的差異,竟還有很深的學問。

如果將 TableA UNION TableB,得到的結果,會類似將 TableA 與 TableB 的資料匯總之後再進行 Distinct 。所以 UNION 後的結果是不會重複的。

至於另一個 UNION ALL 呢? TableA UNION ALL TableB ,所得到的會是 TableA 與 TableB 的資料匯總,即便有重複資料,也都會被保留。

解釋過 UNION 與 UNION ALL 後,可以知道 UNION 比人家多了一個 Distinct 的動作,而這一額外動作就會對整個查詢效能造成影響,尤其是當你的資料量很大時,差異就會更明顯。

舉例來說,我建了2個暫存資料表,分別各放幾筆測試資料。

create table #tmp1 (t_Name varchar(30))
create table #tmp2 (t_Name varchar(30))
 
insert into #tmp1(t_Name) values ('paladin')
insert into #tmp1(t_Name) values ('hugo')
insert into #tmp1(t_Name) values ('ken')
insert into #tmp1(t_Name) values ('lillian')
insert into #tmp1(t_Name) values ('panda')
 
insert into #tmp2(t_Name) values ('polly')
insert into #tmp2(t_Name) values ('keen')
insert into #tmp2(t_Name) values ('hana')
insert into #tmp2(t_Name) values ('gemma')

select t_Name from #tmp1
union
select t_Name from #tmp2
 
 
select t_Name from #tmp1
union all
select t_Name from #tmp2

透過「顯示估計執行計畫」,可以得到下面的結果:


透過執行計畫可以瞭解, UNION 多了一個相異排序(Distinct Sort) 動作,這額外的動作,致使他的執行效能比 UNION ALL 慢了些。但是自己實際遇到的資料量,遠比這幾筆測試資料多太多了。於是修改了測試資料的筆數,並將測試數據列述如後。



declare @i_count int
set @i_count=0
 
while (@i_count<100000)  -- 分別用 1000,10000,100000
begin
 insert into #tmp1(t_Name) values ('paladin@@')
 insert into #tmp2(t_Name) values ('panda@@')
 set @i_count=@i_count+1
end


當測試資料達10萬筆之後,兩種語法的效能相差了 3 倍之多。

所以,如果您所要 UNION 的兩個資料表並不會有重複資料或是本身您並不在意有重複資料,改用 UNION ALL 會大大提昇整體 SQL 的查詢效率。

參考:

01.SQL SERVER – Union vs. Union All – Which is better for performance?

02.The effects UNION in a SQL query



2 則留言:

  1. 師兄你好. 謝謝你的文章.
    但有個小小的問題 想請教

    小弟 用 Union All 來 做 大量 Data insert to Table.
    過往都沒有事.
    但 近日發現 如果Table 里 有一個Field 的 datatype 是 money 時. 問題就出現.
    當那個field 中 有 小數 的 時候.
    系統 報 稱
    Expression evaluation caused an overflow. [ Name of function (if known) = ]

    請問是甚麼原因呢?

    奇怪的是 我 把 insert 的 數量 減至每次5-10條, 這個Error 又不會出現.
    這有是甚麼原因呢?

    我用的是 Compact Ce 3.5 Sp2.
    DataSource 是 sdf.

    回覆刪除
  2. KC 您好,

    對於 SQL CE ,自己很像還沒裝過哩。但您所提到的問題,似乎是在 insert table 時出錯,但跟有沒有使用 Union All 真的有關係嗎?如果不使用 Union All,暫時分批次將有小數點的資料 insert table,是否問題也會出現,如果是的話,懷疑會不會是資料的關係。

    另外,透過 Union 所得到的結果,如果有 Money 欄位的話,他的長度會是目前所有資料的最大值,這時要觀察是否有超過 Money 欄位的長度設計。由下面文章可以知道,是 max(s1, s2),

    http://msdn.microsoft.com/en-us/library/ms190476.aspx


    或許幫不上忙,但謝謝您提供一個很特別的使用經驗。

    回覆刪除