【问题标题】:Performance issue in merge statement合并语句中的性能问题
【发布时间】:2013-03-11 15:02:06
【问题描述】:

我有如下合并语句

    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 个这样的集合,并且同一个查询运行得非常快,但从今天开始,它变得非常慢。我不知道出了什么问题。

注意:查询

从 TABLEA 中选择 WITH(NOLOCK) INNER JOIN TableB .....

在所有场景中都需要 20 秒。

【问题讨论】:

  • 您是否在sys.dm_exec_requests 中检查了blocking_session_idwait_type_desc?这里的任何人都很难猜到为什么要花很长时间。
  • 另外你可能要小心MERGE - 我不想听起来像小鸡,但我在这篇文章的底部强调了十二个尚未解决的错误: sqlperformance.com/2013/02/t-sql-queries/another-merge-bug
  • @AaronBertrand +1 提及链接。现在我相信我应该改变我的查询而不是挖掘这个问题。 :)

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


【解决方案1】:

虽然MERGE 语法更好,并且似乎承诺更好的原子性和无竞争条件 (but doesn't, unless you add HOLDLOCK, as this Dan Guzman post demonstrates),但我仍然觉得还是坚持使用旧式更好,单独的插入/更新方法。主要原因不是语法难学(确实如此),或者难以解决并发问题(事实并非如此),而是存在几个未解决的错误 - 即使在 SQL Server 2012 中也是如此仍然 - 涉及此操作。 I point over 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 和其他几个人加入了 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
  );

对于性能问题,您需要查看会话的等待情况(Plan Explorer* 可以通过为您启动扩展事件会话来帮助解决这个问题),或者至少,blocking_session_id 和 @ 987654333@ in sys.dm_exec_requests 查询运行时。

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

【讨论】:

    猜你喜欢
    • 2021-08-09
    • 2021-12-04
    • 1970-01-01
    • 2013-05-11
    • 1970-01-01
    • 2020-12-22
    • 2022-11-10
    • 2011-07-01
    • 1970-01-01
    相关资源
    最近更新 更多