Performance issue in merge statement

五迷三道 提交于 2021-01-28 05:57:52

问题


I have a merge statement like below

    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
                ;

For the first set of records (around 300,000) it is working perfectly and executing in just 30 seconds. But for the second set of records (around 300,000) it is taking more than an hour.

Two days back I have loaded 50 sets like that and the same query was working lightning fast, but from today it is damn slow. I have no idea what is going wrong.

Note: Query

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

is taking 20 seconds in all scenerios.


回答1:


While the MERGE syntax is nicer, and it seems to promise better atomicity and no race conditions (but doesn't, unless you add HOLDLOCK, as this Dan Guzman post demonstrates), I still feel like it is better to hang onto the old-style, separate insert/update methodology. The primary reason is not that the syntax is hard to learn (which it is), or that it is difficult to work around the concurrency issues (it isn't), but rather that there are several unresolved bugs - even in SQL Server 2012 still - involving this operation. I point a dozen of them out in this post that talks about yet another MERGE bug that has been fixed recently. I also go into more detail in a cautionary tip posted here.

As I suggested in a comment, I don't want to sound the alarms that the sky is falling, but I'm really not all that interested in switching to MERGE until there are far fewer active bugs. So I would recommend sticking with an old-fashioned UPSERT for now, even though the actual syntax you're using might not be the source of the performance problem you're having anyway.

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

For the performance issue, you'll want to look into your session's waits (SQL Sentry's Plan Explorer PRO* can help with that, by firing up an Extended Events session for you), or at the very least, blocking_session_id and wait_type_desc in sys.dm_exec_requests while the query is running.

*Disclaimer: I work for SQL Sentry.



来源:https://stackoverflow.com/questions/15341831/performance-issue-in-merge-statement

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!