合并声明中的性能问题

时间:2013-03-11 15:02:07

标签: sql-server-2008-r2 merge-statement

我有一个合并声明,如下所示

    MERGE DESTINATION AS DST
 USING ( SELECT <Some_Columns> FROM TABLEA WITH(NOLOCK) INNER JOIN TableB .....

       ) AS SRC
   ON(
     <some conditions>
   )

 WHEN MATCHED THEN 
    UPDATE SET column1 = src.column1
              ...............
              ,Modified_By = @PackageName
              ,Modified_Date = GETDATE() 

 WHEN NOT MATCHED THEN 

    INSERT (<Some_Columns>)
    VALUES(<Some_Columns>)

         OUTPUT        
                  $action, inserted.key'inserted'
                   INTO @tableVar
                ;

对于第一组记录(大约300,000),它运行良好,只需30秒即可执行。 但是对于第二组记录(大约300,000),它需要一个多小时。

两天前我已经加载了50套这样的设备,同样的查询工作速度很快,但是从今天起它很慢。我不知道出了什么问题。

注意:查询

  

SELECT FROM TABLEA WITH(NOLOCK)INNER JOIN TableB .....

所有场景都需要20秒。

1 个答案:

答案 0 :(得分:4)

虽然MERGE语法更好,并且似乎承诺更好的原子性和没有竞争条件(but doesn't, unless you add HOLDLOCK, as this Dan Guzman post demonstrates),但我仍然认为最好挂起旧式的独立插入/更新方法。主要原因不是语法难以学习(它是什么),或者难以解决并发问题(它不是),而是有几个未解决的错误 - 即使在SQL中也是如此Server 2012仍然 - 涉及此操作。 I point a dozen of them out in this post that talks about yet another MERGE bug that has been fixed recently。我也是go into more detail in a cautionary tip posted here

正如我在评论中所说的那样,我不想发出天空正在下降的警报,但我真的不感兴趣转换到MERGE直到有远活动错误减少。因此,我建议暂时坚持使用老式的UPSERT,即使您使用的实际语法可能不是您反正遇到的性能问题的根源。

UPDATE dest SET column1 = src.column1
  FROM dbo.DestinationTable AS dest
  INNER JOIN (some join) AS src
  ON (some condition);

INSERT dest(...) SELECT cols
  FROM (some join) AS src
  WHERE NOT EXISTS 
  (
    SELECT 1 FROM dbo.DestinationTable
    WHERE key = src.key
  );

对于性能问题,您希望查看会话的等待(SQL Sentry's Plan Explorer PRO *可以为您提供帮助,为您启动扩展事件会话),或者查询正在运行时,blocking_session_id中的wait_type_descsys.dm_exec_requests非常至少。

*免责声明:我为SQL Sentry工作。