1

表A(表合併成)擁有九萬行 表B(源表)有3,677行 我希望這個合併非常快,但它採取30分鐘(和計數)。 如何優化運行速度?SQL合併 - 我該如何優化?

ALTER PROCEDURE [dbo].[MergeAddressFromGraph] 
-- no params 

AS BEGIN - SET NOCOUNT ON加入是爲了避免額外的結果集 - 用SELECT語句的干擾。 SET NOCOUNT ON;

-- first add fids to the MergeFundraiserNameAddress table instead of the temp table? 

SELECT fundraiserid, ein 
INTO #fids 
FROM bb02_fundraiser 

BEGIN TRAN; 
MERGE BB02_FundraiserNameAddress AS T 
USING 
( 
    select f.fundraiserid, 
      n.addresslines, 
      n.town, 
      n.county, 
      n.postcode, 
      n.country, 
      n.fulladdress, 
      n.ein 
    from MergeFundraiserNameAddress n 
     join bb02_fundraiser f 
     on f.ein = n.ein and f.isdefault = 1 
    group by n.ein, 
      f.fundraiserid, 
      n.addresslines, 
      n.town, 
      n.county, 
      n.postcode, 
      n.country, 
      n.fulladdress 

) AS S 
ON (T.fundraiserid in((select fundraiserid from #fids where ein = S.ein))) 

WHEN MATCHED 
    THEN UPDATE 
     SET  
       -- ADDRESS 
       T.addresslines = S.addresslines 
       ,T.town = S.town 
       ,T.county = S.county 
       ,T.postcode = S.postcode 
       ,T.country = S.country 
       ,T.fulladdress = S.fulladdress 

; 

DELETE FROM MergeFundraiserNameAddress 

COMMIT TRAN; 

drop table #fids 

END

UPDATE 我能夠改善現在運行在短短的幾秒鐘的存儲過程。我加入了臨時表而不是bb02_fundraiser表,並刪除了ON子句中的子查詢。

我現在認識到合併是沒有必要,我可以用一個更新替代,但我現在很確定這個正確的,因爲可能很快在重構需要一個INSERT。

更新的存儲過程下 IF OBJECT_ID( 'tempdb中..#FIDS')IS NOT NULL DROP TABLE #fids

SELECT fundraiserid, ein 
INTO #fids 
FROM bb02_fundraiser 
where isdefault = 1 

BEGIN TRAN; 
MERGE BB02_FundraiserNameAddress AS T 
USING 
( 
    select f.fundraiserid, 
      n.addresslines, 
      n.town, 
      n.county, 
      n.postcode, 
      n.country, 
      n.fulladdress, 
      n.ein 
    from MergeFundraiserNameAddress n 
     join #fids f 
     on f.ein = n.ein 
    group by n.ein, 
      f.fundraiserid, 
      n.addresslines, 
      n.town, 
      n.county, 
      n.postcode, 
      n.country, 
      n.fulladdress 

) AS S 
ON (T.fundraiserid = S.fundraiserid) 

WHEN MATCHED 
    THEN UPDATE 
     SET  
       -- ADDRESS 
       T.addresslines = S.addresslines 
       ,T.town = S.town 
       ,T.county = S.county 
       ,T.postcode = S.postcode 
       ,T.country = S.country 
       ,T.fulladdress = S.fulladdress 

; 

DELETE FROM MergeFundraiserNameAddress 

COMMIT TRAN; 

IF OBJECT_ID('tempdb..#fids') IS NOT NULL 
DROP TABLE #fids 
+0

請發佈執行計劃。你是對的 - 我們可以很快就做到這一點。 – usr

+2

你爲什麼要使用合併,如果唯一可能的結果是更新? ([這是爲什麼你可能想要謹慎使用MERGE](http://www.mssqltips.com/sqlservertip/3074/use-caution-with-sql-servers-merge-statement/)。) –

+0

此外,也許它正在被阻止。當它運行30分鐘時,sys.dm_exec_requests會說什麼?此DMV可以向您顯示blocking_session_id以及嘗試運行MERGE的session_id的等待類型。 –

回答

0

下面看看獨此說法沒有工作適合你。

UPDATE T 
SET T.addresslines = n.addresslines 
     ,T.town = n.town 
     ,T.county = n.county 
     ,T.postcode = n.postcode 
     ,T.country = n.country 
     ,T.fulladdress = n.fulladdress 
    from MergeFundraiserNameAddress n join bb02_fundraiser f 
    on f.ein = n.ein and f.isdefault = 1 
    INNER JOIN BB02_FundraiserNameAddress T 
    ON T.fundraiserid = f.fundraiserid AND T.ein = f.ein 
group by n.ein, 
      f.fundraiserid, 
      n.addresslines, 
      n.town, 
      n.county, 
      n.postcode, 
      n.country, 
      n.fulladdress 

正如其他用戶在您的評論中提到的那樣,爲什麼只在更新記錄時使用MERGE語句。當您執行多個操作(如UPDATE,DELETE和INSERT)時,會使用MERGE語句。

由於您只更新記錄,沒有必要合併聲明。

原因對於性能緩慢

既然你得到一個臨時表中的所有記錄,然後與其他表連接,並在該臨時表中沒有創建任何索引,沒有任何指標會傷害查詢性能。

當你做一個SELECT * INTO #TempTable FROM Some_Table就會帶來從Some_Table所有的數據到一個臨時表,但不是指標。你可以通過運行這個簡單的查詢來查看你的自我

select * from tempdb.sys.indexes 
where object_id = (select object_id 
        from tempdb.sys.objects 
        where name LIKE '#TempTable%') 
+0

不錯的建議,但3000行表格上的索引不會產生任何影響 –

+0

@ElectricLlama沒錯,但如果OP在抱怨性能,那麼第一個嫌疑人就是他的代碼中的Temp表。 –

+0

我不同意,我們有一個90,000行表從3677行表更新,我的懷疑將在90,000行表上。通過觀察查詢計劃和I/O等,懷疑可以變成確定性。 –

0

也爲什麼刪除的時候可以截斷。

truncate table MergeFundraiserNameAddress

+0

我不是SQL專家,所以還有很多事情我不知道。感謝您的建議。我查了截斷vs刪除,看看你的意思。 http://stackoverflow.com/questions/3256242/pros-cons-of-truncate-vs-delete-from – Induster