簡単に言えば、
オプティマイザによるインデックス付きビューのインデックスの選択をクエリする要因は何ですか?
私にとって、インデックス付きビューは、オプティマイザーがインデックスを選択する方法について理解していることに反しているようです。私が見てきた、これは前に尋ねたが、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行の出力
プロファイラーの出力
上位4行にはヒントがありません。下部の4行はヒントを使用しています。
SQLPlan形式の両方の実行計画の実行計画
GitHub Gist
ヒント実行計画はありません-Mr. SQLに提供したクラスター化インデックスを使用しませんか?3つのフィルターフィールドにクラスター化されています。それを試してください、あなたはそれを好きかもしれません。
ヒントを使用するときの簡単な計画。