Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/74.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
SQL合并-如何对此进行优化?_Sql_Sql Server_Query Optimization_Sql Optimization_Sql Merge - Fatal编程技术网

SQL合并-如何对此进行优化?

SQL合并-如何对此进行优化?,sql,sql-server,query-optimization,sql-optimization,sql-merge,Sql,Sql Server,Query Optimization,Sql Optimization,Sql Merge,表要合并到的表有90000行 表B源表有3677行 我希望这个合并非常快,但它需要30分钟和计数。 如何对其进行优化以更快地运行 ALTER PROCEDURE [dbo].[MergeAddressFromGraph] -- no params 作为 开始 -已添加SET NOCOUNT以防止额外的结果集丢失 -干扰SELECT语句。 不计数 -- first add fids to the MergeFundraiserNameAddress table instead of the t

表要合并到的表有90000行 表B源表有3677行 我希望这个合并非常快,但它需要30分钟和计数。 如何对其进行优化以更快地运行

ALTER PROCEDURE [dbo].[MergeAddressFromGraph] 
-- no params
作为 开始 -已添加SET NOCOUNT以防止额外的结果集丢失 -干扰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
结束

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

我现在意识到合并是不必要的,我本可以用更新来代替,但我现在同意这一点,因为重构中可能很快就需要插入

下面更新了存储过程 如果对象_ID'tempdb..fids'不为空 升降台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

看看下面这句话是否适合你

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语句用于执行更新、删除和插入等多项操作

因为您只更新记录,所以不需要merge语句

性能缓慢的原因

由于要获取临时表中的所有记录,然后将其与其他表连接,并且不在该临时表上创建任何索引,因此缺少任何索引都会影响查询性能

当您从某个_表中执行SELECT*INTO TENTABLE时,它会将某个_表中的所有数据带入临时表,但不会将索引带入临时表。您可以通过运行这个简单的查询来查看自己

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

还有,既然可以截断,为什么还要删除呢


截断表MergeFundraiserNameAddress

请发布执行计划。你说得对-我们可以很快完成。如果唯一可能的结果是更新,为什么要使用合并。而且,它可能正在被封锁。当运行30分钟时,sys.dm_exec_请求会说什么?此DMV可以显示阻止会话id以及会话id尝试运行合并的等待类型。建议不错,但3000行表上的索引将不起作用difference@ElectricLlama是的,但如果OP抱怨性能,第一个嫌疑犯将是他的代码中的临时表。我不同意,我们有一个90000行的表正在从一个3677行的表更新,我怀疑是在90000行的表上。通过观察查询计划和I/O等,可以将怀疑转化为确定性。@electrialma我同意你的观点,但为什么你坚持认为用户的临时表中大约有3000行。显然,如果查询速度慢,任何人都会在创建索引或任何东西之前首先看到执行计划,但在这种特殊情况下,如果没有提供执行计划,我只是猜测,我的猜测和你的一样好,因为你和我都没有这个查询的行数或执行计划:他在评论中提到了行数。当然,行数可能会改变,在这种情况下,索引肯定是值得的。我不是SQL专家,所以还有很多事情我不知道。谢谢你的建议。我查了一下truncate vs delete,明白你的意思了。