2011-06-09 17 views
2

私が照会しているテーブルの1つでは、主キーではないキー上にクラスタード・インデックスが作成されました。 (理由は分かりません)なぜSQL Serverはクラスタ化されていないインデックスよりもクラスタ化インデックススキャンを選択するのですか?

ただし、このテーブルのプライマリキーにはクラスタ化されていないインデックスがあります。

実行計画では、SQLは、クエリで使用しているプラ​​イマリキーの非クラスタ化インデックスではなく、クラスタ化インデックスを選択しています。

SQLがこれを行う理由はありますか?代わりに非クラスタ化インデックスをSQLに選択させるにはどうすればよいですか?より詳細な情報を追加は


テーブルには、多くの分野があり、クエリが参加し、多くが含まれています。それを少し抽象化しましょう。

テーブル定義は次のようになります。

SlowTable 
[SlowTable_id] [int] IDENTITY(200000000,1) NOT NULL, 
[fk1Field] [int] NULL, 
[fk2Field] [int] NULL, 
[other1Field] [varchar] NULL, 
etc. etc... 

し、このテーブルのインデックスは、次のとおりです。

fk1Field (Clustered) 
SlowTable_id (Non-Unique, Non-Clustered) 
fk2Field (Non-Unique, Non-Clustered) 
... and 14 other Non-Unique, Non-Clustered indices on other fields 

は、おそらく多くは、彼らがこれを選択した理由fk1Fieldに対して行わより多くのクエリがありますクラスタード・インデックスの基礎。

私が持っているクエリは、ビューを使用しています。

SELECT 
    [field list] 
FROM 
    SourceTable1 S1 
    INNER JOIN SourceTable2 S2 
     ON S2.S2_id = S1.S2_id 
    INNER JOIN SourceTable3 S3 
     ON S3.S3_id = S2.S3_id 
    INNER JOIN SlowTable ST 
     ON ST.SlowTable_id = S1.SlowTable_id 
    INNER JOIN [many other tables, around 7 more...] 

実行計画は、関係するノードが

Clustered Index Scan (Clustered) 
SlowTable.fk1Field 
Cost: 77% 
に太い矢印が付き

Hash Match 
(Inner Join) 
Cost: 9% 

を言うと、かなり大きいです

私はこれが問題の詳細を十分に説明してくれることを願っています。

ありがとうございます!


付録2: 私の以前の投稿への修正。ビューにはwhere句がありません。単なる一連の内部結合です。実行計画は、次のような複雑なクエリで、ビュー(SLOW_VIEWとして表示)を使用するInsertステートメントから取得されました。

(このストアドプロシージャは、いくつかの合計量の比例分割を行うことです合計に対する割合として計算された重みに基づいて、レコード、この模倣は、他のアカウントに、1つのアカウント、たとえば、から値を配布)

INSERT INTO dbo.WDTD(
    FieldA, 
    FieldB, 
    GWB_id, 
    C_id, 
    FieldC, 
    PG_id, 
    FieldD, 
    FieldE, 
    O_id, 
    FieldF, 
    FieldG, 
    FieldH, 
    FieldI, 
    GWBIH_id, 
    T_id, 
    JO_id, 
    PC_id, 
    PP_id, 
    FieldJ, 
    FieldK, 
    FieldL, 
    FieldM, 
    FieldN, 
    FieldO, 
    FieldP, 
    FieldQ, 
    FieldS) 
SELECT DISTINCT 
    @FieldA FieldA, 
    GETDATE() FieldB, 
    @Parameter1 GWB_id, 
    GWBIH.C_id C_id, 
    P.FieldT FieldC, 
    P.PG_id PG_id, 
    PAM.FieldD FieldD, 
    PP.FieldU FieldE, 
    GWBIH.O_id O_id, 
    CO.FieldF FieldF, 
    CO.FieldG FieldG, 
    PSAM.FieldH FieldH, 
    PSAM.FieldI FieldI, 
    SOURCE.GWBIH_id GWBIH_id, 
    ' ' T_id, 
    GWBIH.JO_id JO_id, 
    SOURCE.PC_id PC_id, 
    GWB.PP_id, 
    SOURCE.FieldJ FieldJ, 
    1 FieldK, 
    ROUND((SUM(GWBIH.Total)/AGG.Total) * SOURCE.Total, 2) FieldL, 
    ROUND((SUM(GWBIH.Total)/AGG.Total) * SOURCE.Total, 2) FieldM, 
    0 FieldN, 
    ' ' FieldO, 
    ESGM.FieldP_flag FieldP, 
    SOURCE.FieldQ FieldQ, 
    '[UNPROCESSED]' 
FROM 
    dbo.Table1 GWBIH 
    INNER JOIN dbo.Table2 GWBPH 
     ON GWBPH.GWBP_id = GWBIH.GWBP_id 
    INNER JOIN dbo.Table3 GWB 
     ON GWB.GWB_id = GWBPH.GWB_id 
    INNER JOIN dbo.Table4 P 
     ON P.P_id = GWBPH.P_id 
    INNER JOIN dbo.Table5 ESGM 
     ON ESGM.ET_id = P.ET_id 
    INNER JOIN dbo.Table6 PAM 
     ON PAM.PG_id = P.PG_id 
    INNER JOIN dbo.Table7 O 
     ON O.dboffcode = GWBIH.O_id 
    INNER JOIN dbo.Table8 CO 
     ON 
      CO.Country_id = O.Country_id 
      AND CO.Brand_id = O.Brand_id 
    INNER JOIN dbo.Table9 PSAM 
     ON PSAM.Office_id = GWBIH.O_id 
    INNER JOIN dbo.Table10 PCM 
     ON PCM.PC_id = GWBIH.PC_id 
    INNER JOIN dbo.Table11 PC 
     ON PC.PC_id = GWBIH.PC_id 
    INNER JOIN dbo.Table12 PP 
     ON PP.PP_id = GWB.PP_id 
      -- THIS IS THE VIEW THAT CONTAINS THE CLUSTERED INDEX SCAN 
    INNER JOIN dbo.SLOW_VIEW GL 
     ON GL.JO_id = GWBIH.JO_id 
    INNER JOIN (
     SELECT 
      GWBIH.C_id C_id, 
      GWBPH.GWB_id, 
      SUM(GWBIH.Total) Total 
     FROM 
      dbo.Table1 GWBIH 
      INNER JOIN dbo.Table2 GWBPH 
       ON GWBPH.GWBP_id = GWBIH.GWBP_id 
      INNER JOIN dbo.Table10 PCM 
       ON PCM.PC_id = GWBIH.PC_id 
     WHERE 
      PCM.Split_flag = 0 
      AND GWBIH.JO_id IS NOT NULL 
     GROUP BY 
      GWBIH.C_id, 
      GWBPH.GWB_id 
      ) AGG 
     ON AGG.C_id = GWBIH.C_id 
      AND AGG.GWB_id = GWBPH.GWB_id 
    INNER JOIN (
     SELECT 
      GWBIH.GWBIH_id GWBIH_id, 
      GWBIH.C_id C_id, 
      GWBIH.FieldQ FieldQ, 
      GWBP.GWB_id GWB_id, 
      PCM.PC_id PC_id, 
      CASE 
      WHEN WT.FieldS IS NOT NULL 
       THEN WT.FieldS 
      WHEN WT.FieldS IS NULL 
       THEN PCMS.FieldT 
      END FieldJ, 
      SUM(GWBIH.Total) Total 
     FROM 
      dbo.Table1 GWBIH 
      INNER JOIN dbo.Table2 GWBP 
       ON GWBP.GWBP_id = GWBIH.GWBP_id 
      INNER JOIN dbo.Table4 P 
       ON P.P_id = GWBP.P_id 
      INNER JOIN dbo.Table10 PCM 
       ON PCM.PC_id = GWBIH.PC_id 
      INNER JOIN dbo.Table11 PCMS 
       ON PCMS.PC_id = PCM.PC_id 
      LEFT JOIN dbo.WT WT 
       ON WT.ET_id = P.ET_id 
       AND WT.PC_id = GWBIH.PC_id 
     WHERE 
      PCM.Split_flag = 1 
     GROUP BY 
      GWBIH.GWBI_id, 
      GWBIH.C_id, 
      GWBIH.FieldQ, 
      GWBP.GWB_id, 
      WT.FieldS, 
      PCM.PC_id, 
      PCMS.ImportCode 
      ) SOURCE 
     ON SOURCE.C_id = GWBIH.C_id 
      AND SOURCE.GWB_id = GWBPH.GWB_id 
WHERE 
    PCM.Split_flag = 0 
    AND AGG.Total > 0 
    AND GWBPH.GWB_id = @Parameter1 
    AND NOT EXISTS (
     SELECT * 
     FROM dbo.WDTD 
     WHERE 
      TD.C_id = GWBIH.C_id 
      AND TD.FieldA = GWBPH.GWB_id 
      AND TD.JO_id = GWBIH.JO_id 
      AND TD.PC_id = SOURCE.PC_id 
      AND TD.GWBIH_id = ' ') 
GROUP BY 
    GWBIH.C_id, 
    P.FieldT, 
    GWBIH.JO_id, 
    GWBIH.O_id, 
    GWBPH.GWB_id, 
    P.PG_id, 
    PAM.FieldD, 
    PP.FieldU, 
    GWBIH.O_id, 
    CO.FieldF, 
    CO.FieldG, 
    PSAM.FieldH, 
    PSAM.FieldI, 
    GWBIH.JO_id, 
    SOURCE.PC_id, 
    GWB.PP_id, 
    SOURCE.FieldJ, 
    ESGM.FieldP_flag, 
    SOURCE.GWBIH_id, 
    SOURCE.FieldQ, 
    AGG.Total, 
    SOURCE.Total 

補遺3:上の実行計画をしていますビューの選択ステートメント、私はこれを参照してください:

Hash Match  <==== Bitmap   <------ etc... 
(Inner Join)   (Bitmap Create) 
Cost: 0%    Cost: 0% 
    ^
    | 
    | 
Parallelism       Clustered Index Scan (Clustered) 
(Repartition Streams) <====  Slow_Table.fk1Field 
Cost: 1%        Cost: 98% 

付録4:問題が見つかりました。Clustered Index Scanは、主キーを参照するmy句を参照するのではなく、何らかの方法で上記のfk1Fieldに関連するフィールドを必要とする別の句です。

+1

詳細情報:テーブル+インデックス+プラン – gbn

+0

関連スキーマ情報、実際の実行プラン、クエリテキストなど、詳細情報なしで正確に絞り込むことはできません。 –

+0

あなたの余分なものinfo *は十分ではありません:WHERE句とGROUP BY句は何ですか?また、すべてのインデックスは単一の列インデックスですか? – gbn

答えて

4

ほとんどの場合の1:インデックスの有効

  • インデックスが条件
  • インデックスがカバーされていないと、SQL Serverが鍵を避けONを/合わないようにする

    • あまりにも多くの行検索

    編集、更新後:彼らはすべて単一であるため、

    あなたのインデックスが役に立ちませんこれにより、クラスタード・インデックス・スキャンが実行されます。

    ON、WHERE、GROUP BY条件に一致するインデックスがSELECTリストのINCLUDESに必要です。

  • 1

    実行中のクエリでレコードの小さなサブセットが選択されていない場合、SQL Serverは「有用でない」非クラスタ化インデックスを無視し、クラスタ化インデックス(この例では、最も可能性が高いのはテーブル内のすべての行) - クエリを実行するために必要なI/Oの量と非クラスタ化された索引の量が、フルスキャンに必要な量を上回るというロジックです。

    テーブルのスキーマ+サンプルクエリを投稿できる場合は、より多くの情報を提供できると確信しています。

    1

    理想的には、どちらかを実行するようにSQL Serverに指示しないでください。または、適切なクエリを実行すると、最適なものを選択できます。クエリヒントは、エンジンを少し操作するために作成されましたが、これをまだ使用する必要はありません。

    プライマリキーがまれであることを別の方法でテーブルをクラスタ化すると便利ですが、プライマリキーが正しいことを保証しながらクラスタリングがデータレイアウトを制御します。

    クエリとスキーマを表示すると、SQL Serverがクラスタ化インデックスを選択する理由を正確に伝えることができます。それ以外の場合は、原因と実行計画を推測するだけです。

    クラスタ化されていないインデックスを考慮するには、クエリに意味を持たせる必要があります。クラスタ化されていないインデックスにクエリが含まれていない場合は、まったく使用されません。

    1

    クラスタ化インデックススキャンは、本質的にテーブルスキャン(クラスタ化インデックスを持つテーブル上)です。あなたは本当に良い答えを得るためにあなたの声明を投稿すべきです。 where句が検索できない場合があります(sargsを参照)。また、多数のレコードを選択している場合、SQL Serverはインデックスを使用せずにテーブルをスキャンし、その後関連する列を検索する必要があります。

    関連する問題