1

以下のようなマージステートメントがあります

    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 秒で実行されます。しかし、2 番目のレコード セット (約 300,000) では、1 時間以上かかります。

2 日前、私はそのようなセットを 50 個ロードしましたが、同じクエリが非常に高速に動作していましたが、今日からは非常に遅くなります。何が問題なのかわかりません。

注: クエリ

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

すべてのシーンで 20 秒かかります。

4

1 に答える 1

4

MERGE構文はより優れており、アトミック性が向上し、競合状態がないことを約束しているように見えますが (ただし、この Dan Guzman の投稿が示すように、追加しない限りそうではありませんHOLDLOCK)、古いスタイルに固執する方が良いと私はまだ感じています。個別の挿入/更新方法。主な理由は、構文を習得するのが難しい (実際) とか、同時実行の問題を回避するのが難しい (そうではない) ということではなく、未解決のバグがいくつかあることです (SQL Server 2012 でも)。まだ-この操作を含みます。この記事では、最近修正されたさらに別のMERGEバグについて説明しています。ここに投稿された注意事項のヒントでも詳しく説明しますと他のいくつかがここでチャイムを鳴らします。

コメントで提案したように、空が落ちているという警報を鳴らしたくはありませんが、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クエリの実行中wait_type_descに調べる必要があります。sys.dm_exec_requests

*免責事項: 以前は SQL Sentry で働いていました。

于 2013-03-11T19:25:30.877 に答える