2012-05-02 3 views
7

データベースには、30列の2つのテーブルをwhere条件で結合してテーブルを更新するストアドプロシージャーがあります。 SQLの一般的な形式は次のとおりです。多くのISNULLを持つ多数列のUPDATE-JOINには時間がかかりますか?

UPDATE Target 
SET col1 = Source.col1 
INNER JOIN Source 
on 
ISNULL(Target.Col2, '') = ISNULL(Source.Col2, '') and 
ISNULL(Target.Col3, '') = ISNULL(Source.Col3, '') and 
. 
. 
. 
ISNULL(Target.Col31, '') = ISNULL(Source.Col31, '') and 

クエリプランは次のとおりです。それをあなたのPCに保存して、それを再び開くようにしてください。

enter image description here

ソーステーブルは65Mレコード、ターゲット165Mを持っています。これまではかなりの時間がかかっていました。どのようにクエリが醜い、潜在的に非効率的であるかを考慮すると、私はこれを驚くべきものと見なします。今月は1.5時間稼働し、プロセッサーの100%を使用しており、それを強制終了しなければならなかった。

以下のクエリを即興して時間通りに実行する方法を教えてください。

30列の結合条件で使用されるいくつかの列に単一の列のインデックスがあります。

私はISNULL関数を知っており、30列の結合はナットであり、これは悪い設計です。私を責めないで、私はこの経済を継承しました。

残念ながら、再設計の時間はありません。助言がありますか?

+4

先月から何が変更されましたか? –

+2

すべてのNULLを ''''に更新してから、ISNULLなしでクエリを実行してください。しかし、レムスの質問は非常に関連しています。 – MatBailie

+1

あなたはマージとしてそれを書き直すことを考えましたか?これらの列をnull不可能にして60個のISNULL呼び出しを排除することを検討しましたか? –

答えて

5
  1. 私は以前のクエリがハッシュが(どのそれが必要)参加何とか基数推定は今間違ったことがあり、参加ループを取得使用と思われる推定実行プラン
  2. のスクリーンショットを投稿してください。クエリにハッシュ結合ヒントをスラップして、これが修正されているかどうかを確認します(INNER HASH JOIN)。正確な計画を立てたら、もっと言えます。
  3. 等価を(A1 = A2 OR (A1 IS NULL AND A2 IS NULL))に変更してください。 SQL Serverは実際にこのパターンを認識し、内部的に「愚かなヌルセマンティクスを持たない完全一致」に変換します。 null値でも索引を検索できます。

これがうまくいかない場合は、(3)の手順を実行し、col1を含むcol2-col31にカバーインデックスを作成してください。これにより、この場合に可能な最も効率的な計画であるマージ結合が得られます。それは本当に速いです。警告:これは、テーブルのディスク上のサイズを2倍にし、更新を遅くします。

+1

私はプランを追加しました。私の修正された記事を見てください。 ISNULL関数を削除することについてのあなたのコメントに関して、A1またはA2がnullであるが両方ではない場合はどうなるでしょうか? – ChadD

+0

ええ、ハッシュ結合のヒントがこれを修正します。 – usr

+0

@usrクエリに1を追加するには? –

0

DBAは、問合せアナライザの推奨事項に従って、30列すべてを含む索引を追加することを提案しました。ほとんどの場合、「含まれる」列です。これにより、クエリが完了することができました。翌月には、通常1.5時間で実行されるSQLと同じアップデートSQLが24時間で完了しませんでした。 Update statisticsを実行すると、1時間で終了しました。

関連する問題