選択されているインデックス付きビューのクラスター化インデックスに含まれる要因は何ですか?


19

簡単に言えば、
オプティマイザによるインデックス付きビューのインデックスの選択をクエリする要因は何ですか?

私にとって、インデックス付きビューは、オプティマイザーがインデックスを選択する方法について理解していることに反しているようです。私が見てきた、これは前に尋ねたが、OPはあまり好評ではなかったです。 私は本当に道しるべを探していますが、擬似的な例を作成してから、多くのDDL、出力、例を含む実際の例を投稿します。

私はEnterprise 2008+を使用していると仮定し、理解します with(noexpand)

疑似の例

この擬似的な例を見てみましょう。22個の結合、17個のフィルター、1000万行のテーブルを横断するサーカスポニーを含むビューを作成します。このビューは、実現するのに高価です(ええ、大文字のE)。SCHEMABINDとビューのインデックスを作成します。それから SELECT a,b FROM AnIndexedView WHERE theClusterKeyField < 84。私を回避するオプティマイザーロジックでは、基になる結合が実行されます。

結果:

  • ヒントなし:720行で4825の読み取り、76ミリ秒で47 CPU、0.30523の推定サブツリーコスト。
  • ヒントあり:17読み取り、720行、4ミリ秒で15 CPU、0.007253の推定サブツリーコスト

ここで何が起こっているのでしょうか?Enterprise 2008、2008 -R2、および2012で試してみました。ビューのインデックスを使用すると考えられるすべてのメトリックで、はるかに効率的です。これはアドホックであるため、パラメータスニッフィングの問題やデータの偏りはありません。

実際の(長い)例

あなたが自虐的なタッチでない限り、おそらくこの部分を読む必要はないでしょう。

バージョン
うん、企業。

Microsoft SQL Server 2012-11.0.2100.60(X64)2012年2月10日19:39:15 Copyright(c)Microsoft Corporation Enterprise Edition(64-bit)on Windows NT 6.2(Build 9200:)(ハイパーバイザー)

景色

CREATE VIEW dbo.TimelineMaterialized    WITH SCHEMABINDING
AS
SELECT  TM.TimelineID,
        TM.TimelineTypeID,
        TM.EmployeeID,
        TM.CreateUTC,
        CUL.CultureCode,
        CASE 
           WHEN TM.CustomerMessageID    > 0 THEN TM.CustomerMessageID
           WHEN TM.CustomerSessionID    > 0 THEN TM.CustomerSessionID
           WHEN TM.NewItemTagID         > 0 THEN TM.NewItemTagID
           WHEN TM.OutfitID             > 0 THEN TM.OutfitID
           WHEN TM.ProductTransactionID > 0 THEN TM.ProductTransactionID
           ELSE 0 END  As HrefId,
        CASE 
          WHEN TM.CustomerMessageID    > 0 THEN IsNull(C.Name, 'N/A')   
          WHEN TM.CustomerSessionID    > 0 THEN IsNull(C.Name, 'N/A')
          WHEN TM.NewItemTagID         > 0 THEN IsNull(NI.Title, 'N/A')
          WHEN TM.OutfitID             > 0 THEN IsNull(O.Name, 'N/A')
          WHEN TM.ProductTransactionID > 0 THEN IsNull(PT_PL.NameLocalized, 'N/A')
                 END as HrefText

FROM       dbo.Timeline TM
INNER JOIN dbo.CustomerSession    CS    ON TM.CustomerSessionID    = CS.CustomerSessionID
INNER JOIN dbo.CustomerMessage    CM    ON TM.CustomerMessageID    = CM.CustomerMessageID
INNER JOIN dbo.Outfit             O     ON PO.OutfitID             = O.OutfitID
INNER JOIN dbo.ProductTransaction PT    ON TM.ProductTransactionID = PT.ProductTransactionID
INNER JOIN dbo.Product            PT_P  ON PT.ProductID            = PT_P.ProductID
INNER JOIN dbo.ProductLang        PT_PL ON PT_P.ProductID          = PT_PL.ProductID
INNER JOIN dbo.Culture            CUL   ON PT_PL.CultureID         = CUL.CultureID
INNER JOIN dbo.NewsItemTag        NIT   ON TM.NewsItemTagID        = NIT.NewsItemTagID
INNER JOIN dbo.NewsItem           NI    ON NIT.NewsItemID          = NI.NewsItemID
INNER JOIN dbo.Customer           C     ON  C.CustomerID = CASE 
                                             WHEN TM.TimelineTypeID = 1 THEN CM.CustomerID 
                                             WHEN TM.TimelineTypeID = 5 THEN CS.CustomerID
                                             ELSE 0 END

WHERE        CUL.IsActive = 1

クラスター化インデックス

CREATE UNIQUE CLUSTERED INDEX PK_TimelineMaterialized  ON 
                   TimelineMaterialized (EmployeeID, CreateUTC, CultureCode, TimelineID)

テストSQL

-- NO HINT - - -  - - -  - - -  - - -  - - - 
SELECT  *                 --yes yes, star is bad ...just a test example
FROM    TimelineMaterialized TM 
WHERE 
            TM.EmployeeID   = 2
        AND TM.CultureCode  = 'en-US'
        AND TM.CreateUTC    > '9/10/2012'
        AND TM.CreateUTC    < '9/11/2012'

-- WITH HINT - - -  - - -  - - -  - - -  - - - 
SELECT  *               
FROM    TimelineMaterialized TM with(noexpand)
WHERE 
            TM.EmployeeID   = 2
        AND TM.CultureCode  = 'en-US'
        AND TM.CreateUTC    > '9/10/2012'
        AND TM.CreateUTC    < '9/11/2012'

結果= 11行の出力

11行の出力-両方のクエリで同じ

プロファイラーの出力
上位4行にはヒントがありません。下部の4行はヒントを使用しています。

プロファイラー

SQLPlan形式の両方の実行計画の実行計画
GitHub Gist

ヒント実行計画はありません-Mr. SQLに提供したクラスター化インデックスを使用しませんか?3つのフィルターフィールドにクラスター化されています。それを試してください、あなたはそれを好きかもしれません。
ヒントなし-巨大な実行計画

ヒントを使用するときの簡単な計画。

ヒントの使用-簡単な実行計画


回答:


26

インデックス付きビューの一致は比較的高価な操作*であるため、オプティマイザーは他の迅速で簡単な変換を最初に試行します。それらが安価な計画(あなたの場合は0.05単位)を生成した場合、最適化は早期に終了します。賭けは、最適化を継続すると、保存した時間よりも多くの時間が消費されることです。オプティマイザーの主な目標は、すぐに「十分な」計画であることを忘れないでください。

ビューでクラスター化インデックスを使用すること自体は高価ではありませんが、論理クエリツリーを潜在的なインデックス付きビューに一致させるプロセスにはコストがかかります。他の質問のコメントで述べたように、クエリのビュー参照は最適化の前に展開されるため、オプティマイザは最初にビューに対してクエリを作成したことを知りません-展開されたツリーのみが表示されますビューはインライン化されていました)。

「十分な計画」とは、オプティマイザーが適切な計画を見つけ、調査段階の早い段階で停止したことを意味します。「タイムアウト」は、現在のフェーズの開始時に自身が「予算」として設定した最適化ステップの数を超えたことを意味します。

予算は、前のフェーズで見つかった最適なプランのコストに基づいて設定されます。このような低コストのクエリ(0.05)では、予算の移動の数は非常に少なく、サンプルクエリに含まれる結合の数を考慮すると、通常の変換によってすぐに使い果たされます(たとえば、内部結合を再配置する方法はたくさんあります) 。

あなたは、インデックス付きビューのマッチングが高価である理由についての詳細を知って興味を持って、そのための最適化および/または唯一のより高価なクエリのためと考えられ、話題に2本のMicrosoftの研究論文があるの後期段階のために残されている場合は、ここ(PDF)とここ(citeseer )。

もう1つの関連する要因は、最適化フェーズ0(トランザクション処理)でインデックス付きビューのマッチングが利用できないことです。

参考文献:

インデックス付きビューと統計

*およびEnterprise Edition(または同等のもの)でのみ利用可能

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