1

表 A(要合并的表)有 90,000 行表 B(源表)有 3,677 行我希望这会很快合并,但需要 30 分钟(并且还在计数)。如何优化它以更快地运行?

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

AS BEGIN -- 添加了 SET NOCOUNT ON 以防止额外的结果集 -- 干扰 SELECT 语句。设置无计数;

-- 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

结尾

更新 我能够改进现在只需几秒钟即可运行的存储过程。我加入了临时表而不是 bb02_fundraiser 表,并删除了 ON 子句中的子查询。

我现在意识到 Merge 不是必需的,我可以使用 Update 代替,但我现在可以接受,因为在重构中可能很快需要 INSERT。

如果 OBJECT_ID('tempdb..#fids') 不是 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
4

2 回答 2

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 语句。MERGE 语句用于执行多个操作,例如 UPDATE 、 DELETE 和 INSERT。

由于您只是更新记录,因此不需要合并语句。

性能缓慢的原因

由于您要获取 Temp 表中的所有记录,然后将其与其他表连接,而不是在该 Temp 表上创建任何索引,因此缺少任何索引会损害查询性能。

当您执行 SELECT * INTO #TempTable FROM Some_Table 时,它​​会将 Some_Table 中的所有数据带入 Temp 表,但不会带入索引。你可以通过运行这个简单的查询来看到你自己

select * from tempdb.sys.indexes
where object_id = (select object_id 
                   from tempdb.sys.objects 
                   where name LIKE '#TempTable%')
于 2013-12-12T22:13:56.870 回答
0

还有为什么可以截断时删除。

截断表 MergeFundraiserNameAddress

于 2013-12-13T09:41:37.537 回答