13

非常に大規模 (300M レコード) で広範な を毎日更新する必要がありますTABLE1。更新のソース データはUTABLE、行の 10% ~ 25% であるTABLE1が狭い別のテーブルにあります。両方のテーブルrecord_idに主キーがあります。

現在、TABLE1次のアプローチを使用して 再作成しています。

<!-- language: sql -->
    1) SELECT (required columns) INTO TMP_TABLE1 
    FROM TABLE1 T join UTABLE U on T.record_id=U.record_id  
    2) DROP TABLE TABLE1  
    3) sp_rename 'TMP_TABLE1', 'TABLE1'

ただし、これには私のサーバー (SQL Server の場合は 60GB の RAM) では 40 分近くかかります。パフォーマンスを 50% 向上させたいと考えています。他にどのようなオプションを試すことができますか?

  1. MERGEそしてUPDATE-以下のコードのようなものは、非常に小さなUTABLEテーブルでのみ高速に動作します-フルサイズでは、すべてがハングします:

    <!-- language: SQL -->
    MERGE TABLE1 as target  
    USING UTABLE as source  
    ON target.record_id = source.record_id   
      WHEN MATCHED THEN   
        UPDATE SET Target.columns=source.columns
    
  2. ROWCOUNT を使用してバッチ MERGE を実行できると聞きましたが、3 億行のテーブルに対して十分な速度が得られるとは思いません。

  3. 役立つ SQL クエリのヒントはありますか?

4

2 に答える 2

11

実際、私はそのようなクエリの一般的な推奨事項を見つけました: SQL Merge または Update を使用するアイデアは非常に賢いものですが、大きくて幅の広いテーブル (つまり240M ) で多くのレコード (つまり75M ) を更新する必要がある場合は失敗します。

以下のクエリのクエリ プランを見るとTABLE SCAN、TABLE1 と finalMERGEで 90% の時間がかかっていることがわかります。

MERGE TABLE1 as Target  
USING UTABLE as source  
ON Target.record_id = source.record_id   
WHEN MATCHED AND (condition) THEN   
    UPDATE SET Target.columns=source.columns

したがって、MERGE を使用するには、次のことを行う必要があります。

  1. 更新する必要がある行の数を減らし、この情報を SQL Server に正しく渡します。これは、UTABLE小さくするかcondition、マージする部分を狭くする追加を指定することで実行できます。
  2. マージされる部分がメモリに収まるようにしてください。そうしないと、クエリの実行が遅くなります。2TABLE1倍短縮したことで、実際のクエリ時間が 11 時間から 40 分に短縮されました。

マークが述べたように、UPDATE構文を使用してWHERE句を使用して、マージする部分を絞り込むことができます。これにより、同じ結果が得られます。TABLE1また、インデックス作成中にインデックスを再構築するために追加の作業が発生するため、インデックス作成は避けてください。MERGE

于 2011-05-17T11:26:00.377 に答える
10

最初に、あなたのボトルネックがどこにあるかを見つけます-あなたのCPUは固定されていますか、それともアイドルですか?言い換えれば、IOサブシステムは負荷を適切に処理できますか?

テーブル全体を再作成すると、IOの負荷が大きくなります。もちろん、テーブルを一時的に2回保存するには、多くのスペースが必要になります。

MERGEを実行する必要がありますか?私が見る限り、単純な更新で十分です。例:

UPDATE
    TABLE1
SET
    ColumnX = UTABLE.ColumnX
    ...
FROM
    TABLE1
INNER JOIN
    UTABLE ON TABLE1.record_id = UTABLE.record_id

ROWCOUNTを使用して更新をバッチ処理することもできますが、実行速度は向上しません。全体的なロックを減らすのに役立つだけです。

また、テーブルにはどのようなインデックスがありますか?更新前にインデックスを無効にし、後で最初からインデックスを再構築する方が速い場合があります(非クラスター化のみ)。

于 2011-05-14T13:09:02.080 に答える