SQL 2005とSQL 2008R2でクエリの実行が異なる


9

私のオフィスには、見苦しいクエリがありますが、運用環境と開発環境(それぞれ20秒と4秒)でかなりうまく実行されます。ただし、テスト環境では4時間以上かかります。SQL2005(+最新のパッチ)は、本番環境および開発環境で実行されています。SQL2008R2はテストで実行されています。

クエリプランを確認したところ、SQL2008R2はリンクサーバーから返された行を格納するために、テーブルスプール(レイジースプール)を介してTempDBを使用していることがわかります。次のステップは、クエリの96.3%を消費しているネストされたループ(左反準結合)を示しています。2つのオペレーター間の境界線は5,398MBです。

SQL 2005のクエリプランでは、tempdbの使用とLeft Anti Semi Joinの使用は示されていません。

以下はサニタイズされたコードであり、実行計画は2005年の計画を上に、2008R2は下を計画しています。

劇的なスローダウンと変化の原因は何ですか?別の実行プランが表示されることを期待していたので、気になりません。クエリ時間の劇的なスローダウンが私を悩ませています。

2008R2バージョンはtempdbを使用しているため、基盤となるハードウェアを確認する必要がありますか?その使用を最適化する方法を確認する必要がありますか?

クエリを記述するより良い方法はありますか?

助けてくれてありがとう。

    INSERT INTO Table1_GroupLock (iGroupID, dLockedDate)
SELECT 
 Table1.iGroupID,
 GETDATE()
FROM Table1
WHERE 
 NOT EXISTS (
  SELECT 1
  FROM LinkedServer.Database.Table2 Alias2
  WHERE 
   (
    Alias2.FirstName + Alias2.LastName = dbo.fnRemoveNonLetter(Table1.FullName)
    AND NOT dbo.fnRemoveNonLetter(Table1.FullName) IS NULL
    AND NOT Alias2.FirstName IS NULL 
    AND NOT Alias2.LastName  IS NULL
   ) OR (
    Alias2.FamilyName = dbo.fnRemoveNonLetter(Table1.FamilyName)
    AND Alias2.Child1Name = dbo.fnRemoveNonLetter(Table1.Child1Name)
    AND NOT dbo.fnRemoveNonLetter(Table1.FamilyName) IS NULL
    AND NOT dbo.fnRemoveNonLetter(Table1.Child1Name) IS NULL
    AND NOT Alias2.Familyname IS NULL
    AND NOT Alias2.Child1Name IS NULL
   ) OR (
    Alias2.StepFamilyName = dbo.fnRemoveNonLetter(Table1.StepFamilyName)
    AND Alias2.StepFamilyNameChild1 = dbo.fnRemoveNonLetter(Table1.StepFamilyNameChild2)
    AND NOT Alias2.StepFamilyName IS NULL
    AND NOT Alias2.StepFamilyNameChild1 IS NULL
    AND NOT dbo.fnRemoveNonLetter(Table1.StepFamilyName) IS NULL
    AND NOT dbo.fnRemoveNonLetter(Table1.StepFamilyNameChild2) IS NULL
   )  
 ) AND NOT EXISTS (
  SELECT 1
  FROM Table3
  INNER JOIN Table4
   ON Table4.FirstNameType = Table3.FirstNameType 
  INNER JOIN table5
   ON table5.LastNameType = Table3.LastNameType 
  WHERE 
   Table3.iGroupID = Table1.iGroupID
   AND Table3.bIsClosed = 0
   AND Table4.sNameTypeConstant = 'new_lastname'
   AND table5.sFirstNameConstant = 'new_firstname'
 )

SQL-2005


SQL2008R2

::編集:: 別のSQL2005インスタンスからクエリを実行しました。「良いもの」とほぼ同じ実行プランです。2008R2インスタンスから2008R2インスタンスよりも、2つの2005バージョンが2008R2リンクサーバーに対してどのように実行されるかはまだわかりません。

コードがいくつかの作業を使用する可能性があることは否定しませんが、それが問題のコードである場合、すべてのトライアルで同じようなexec計画を表示しませんか?SQLのバージョンに関係なく?

::編集:: SP1とCU3を2008R2インスタンスの両方に適用しましたが、まだサイコロはありません。リンクサーバーにコロケーションを具体的に設定しましたが、サイコロはありません。私は特に、ユーザーacctの権限を、サイコロではなく、両方のインスタンスでsysadminに設定しています。私はSQLサーバー2008の内部とトラブルシューティングも覚えています。これをいくつか追跡することができるかどうかを確認します。

ヘルプとヒントをありがとうございました。

::編集:: リンクサーバーにさまざまな権限の変更を行いました。SQLログイン、ドメインログインを使用したり、ユーザーを偽装したり、「このセキュリティコンテキストを使用して作成する」オプションを使用したりしました。サーバーでsysadmin権限を持つリンクサーバーの両側にユーザ​​ーを作成しました。アイデアが足りません。

SQL2005がSQL2008R2と大きく異なるクエリを実行している理由を知りたいのですが。クエリが悪かった場合、SQL2005とSQL2008R2の両方で4時間以上の実行時間が表示されます。

回答:


5

クエリを作り直してください。

検索可能性の問題があり、そこでスカラー関数呼び出しを使用しているだけでなく、クエリにも悪影響を及ぼします。Table2にFullName計算列を作成し、それにインデックスを付けて、インデックスがFirstNameとLastNameを確実に含めるようにすることができます。また、他を助けるインデックスを追加する必要があります

また、「RemoveNonLetter」機能を実行するインラインテーブル値関数を作成し、それを使用するようにクエリを作り直します。おそらく、ここで行ったようにAPPLYを使用します。

そして、ポールの答えが 参照しているバグを間違いなくチェックしてください。

INSERT INTO Table1_GroupLock (iGroupID, dLockedDate)
SELECT 
 Table1.iGroupID,
 GETDATE()
FROM Table1
OUTER APPLY (SELECT NonLettersRemoved FROM dbo.ifnRemoveNonLetter(Table1.FullName)) AS fn (FullName)
OUTER APPLY (SELECT NonLettersRemoved FROM dbo.ifnRemoveNonLetter(Table1.FamilyName)) AS famn (FamilyName)
OUTER APPLY (SELECT NonLettersRemoved FROM dbo.ifnRemoveNonLetter(Table1.Child1Name)) AS c1n (Child1Name)
OUTER APPLY (SELECT NonLettersRemoved FROM dbo.ifnRemoveNonLetter(Table1.StepFamilyName)) AS sfn (StepFamilyName)
OUTER APPLY (SELECT NonLettersRemoved FROM dbo.ifnRemoveNonLetter(Table1.StepFamilyNameChild2)) AS sfnc2 (StepFamilyNameChild2)
WHERE 
 NOT EXISTS (
  SELECT 1
  FROM LinkedServer.Database.Table2 Alias2
  WHERE Alias2.FullName = fn.FullName
  UNION ALL
  SELECT 1
  FROM LinkedServer.Database.Table2 Alias2
  WHERE Alias2.FamilyName = famn.FamilyName AND Alias2.Child1Name = c1n.Child1Name
  UNION ALL
  SELECT 1
  FROM LinkedServer.Database.Table2 Alias2
  WHERE Alias2.StepFamilyName = sfn.StepFamilyName AND Alias2.StepFamilyNameChild1 = sfnc2.StepFamilyNameChild2
 ) 
 AND NOT EXISTS (
  SELECT 1
  FROM Table3
  INNER JOIN Table4
   ON Table4.FirstNameType = Table3.FirstNameType 
  INNER JOIN table5
   ON table5.LastNameType = Table3.LastNameType 
  WHERE 
   Table3.iGroupID = Table1.iGroupID
   AND Table3.bIsClosed = 0
   AND Table4.sNameTypeConstant = 'new_lastname'
   AND table5.sFirstNameConstant = 'new_firstname'
 )
;

6

以前の回答に加えて、プランが反準結合に含まれている場合の既知のカーディナリティ推定バグ原因で、プランが後退する理由が考えられます。KB 2222998を参照してください

2005年の計画が許容できるパフォーマンスを生み出したと仮定すると、サーバーをその修正を含むバージョンに上げる(そしてTF4199がそれをアクティブ化できるようにする)と、「良い」計画に戻ることがわかります。

とはいえ、そのクエリを改善する機会は他にもたくさんあるので、代わりにそうすることに集中する良い機会かもしれません。


5

リモートデータはローカルにスプールされることをお勧めします。

  1. リンクサーバーの設定(照合など)が同じではない
  2. リンクサーバーの設定にもかかわらず、ローカル照合はリモートと同じではありません
  3. 権限が原因で、クエリをリモートで正しく実行できません

ポイント1については、sp_serveroptionを参照してください。
ポイント2については、server / db照合も確認してください。

ポイント3については、Linchi Sheaの記事をご覧ください。

ここでの私の回答に従って、SQL Serverにすべてのデータをローカルで処理するように要求しています: ビューでOPENQUERYを使用することによるパフォーマンスへの影響

編集する

よく見ると、「良い」プランでは1つではなく2つのリモートコールが見られます。これは私がここで言うことを確認します


長い遅れでごめんなさい。1:リンクサーバーの設定を確認しましたが、同じです。2:また、リンクサーバーのプロパティの照合順序を確認し、リモートサーバーに暗黙的に設定しました。3:A / Bテストを行うために現在取り組んでいるセキュリティコンテキスト。私はまだ、大幅に異なるexec計画の背後にあるロジックに頑固に取り組んでいます。R2サーバーからR2サーバーへは、選択(15万行以上をプル)を実行してから結合を実行します。2005年からR2への選択が行われ、リモートサーバーに参加します。両方のシナリオのセキュリティコンテキストは同じです。
RateControl

3

データゴッドからのクエリコメントを書き直してみてください。

また、リンクサーバー側でアクセス許可の問題が発生して、この速度低下につながっていないのかと思います。しばらく前に、このリンクサーバーの速度低下についてブログを書きました。権限を確認する価値があるかもしれません(SQLリンクサーバーですか、それとも別のDBMSですか?後者の場合は、とにかく優れた統計を取得できません)

テスト環境にSQL Server 2005があり、このクエリを試して環境を除外しますか?

アップグレード後に統計を再構築しましたか?


3

この比較には非常に多くの問題があります...どこから始めればいいのか分かりません。

  1. 生産機械とテスト機械の正確な仕様を入手してください。

  2. 両方の環境で、さまざまなリンクされたサーバー間のネットワークリンクを特定します。それらは同じ速度ですか?両方の環境でサーバーが隣り合って配置されていますか?

  3. リンクサーバーを使用しないようにクエリを書き直す方法はありますか?サーバー間でテーブルを結合すると、トポロジの変更に対して脆弱なままになり、ほとんどの場合、サーバーの速度は非常に遅くなります。

  4. NOTおよびORを使用すると、通常、全表スキャンが行われます。クエリを書き直してください。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.