2016-11-12 8 views
3

数百万行のテーブルがCPU使用量が多いテーブルでdatepart(day, BornDate)および/または月までにクエリを実行する必要があります。datepartのインデックス付きビュー、datepartのクエリでインデックスが使用されていません

インデックス付きビュー内の非クラスタ化インデックスをインデックス作成済みビューのdatepart(day, BornDate)列に作成しても、datepart列でインデックス付きビューを使用しようとしました。しかし実行計画では依然として、基礎となるテーブルのdatepartを使用してクエリが計算されていることがわかります。

私が実行したクエリは、次のとおりである。

set statistics time on 
SELECT count(1) FROM [dbo].[DemandsBornDateParts] where borndateday = 5 OPTION (RECOMPILE) 
set statistics time off 

私は、基になるテーブルに向け、同じクエリになかれそれを比較:

set statistics time on 
select count(1) from dbo.Demands where DAY(borndate) = 5 
set statistics time off 

彼らの両方がして、ほぼ同じクエリ・プランを表示しますほぼ同じサブツリー・コスト、CPUおよび経過時間、両方とも述語でクラスター化された索引スキャンを実行するdatepart(day,[dbo].[Demands].[BornDate])=(5)

ビューは次のように定義されます。

GO 
--Set the options to support indexed views. 
SET NUMERIC_ROUNDABORT OFF; 
SET ANSI_PADDING, ANSI_WARNINGS, CONCAT_NULL_YIELDS_NULL, ARITHABORT, 
    QUOTED_IDENTIFIER, ANSI_NULLS ON; 
GO 
--Create view with schemabinding. 
IF OBJECT_ID ('dbo.DemandsBornDateParts', 'view') IS NOT NULL 
DROP VIEW dbo.DemandsBornDateParts ; 
GO 
CREATE VIEW dbo.DemandsBornDateParts 
WITH SCHEMABINDING 
AS 
    SELECT id, 
      Datepart(DAY, borndate) AS BornDateDay, 
      Datepart(MONTH, borndate) AS BornDateMonth, 
      Datepart(YEAR, borndate) AS BornDateYear 
    FROM DBO.demands 
GO 

--Create an index on the view. 
CREATE UNIQUE CLUSTERED INDEX [PK_dbo.DemandsBornDateParts] 
    ON dbo.DemandsBornDateParts (Id); 
GO 
CREATE NONCLUSTERED INDEX [IX_BornDateDay] ON [dbo].[DemandsBornDateParts] 
(
    [BornDateDay] ASC 
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 
GO 

どのように私は何度も何度もdatepartを再計算せずに、持続/インデックス付きの列を使用して達成することができますか?私は永続的な列を使用することはできません、私はビューを使用する必要があります。

+0

そのテーブルの統計情報を更新してみてください。これは、クエリプランがあなたのインデックスを考慮していない1つの理由かもしれません.. –

+1

TTによって投稿された記事で指摘されているように、問題は、私たちが強制的に展開しない限り、あまりにも。 –

+0

情報ありがとうございました@MichalŘehout –

答えて

3

クエリのビュー名の後にWITH(NOEXPAND)を追加します。 Table Hintsのドキュメントから:

NOEXPAND

クエリオプティマイザがクエリを処理するときに任意のインデックス付きビューは、基礎となるテーブルにアクセスするために拡張されていないことを指定します。クエリオプティマイザは、ビューをクラスタ化インデックスを持つテーブルのように扱います。 NOEXPANDは、索引付けされたビューにのみ適用されます。

と同じページにRemarks on Using NOEXPANDから:NOEXPANDオプションを指定して、インデックス付きビューのインデックスを使用するようにオプティマイザを強制的に

+0

これは魅力的ですが、なぜSQLサーバが暗黙的にそれを使用しないのでしょうか?問題は、ビューをEFコードの最初のエンティティにマップすることです。これは、簡単に行うには、ヒントのない簡単なクエリでなければなりません。 –

+0

@MichalŘehoutクエリオプティマイザが最適ですが、必ずしも正しいとは限りません。私は、ヒューリスティックや、クエリのパフォーマンスに関するエンジン開発者からのいくつかの洞察から、デフォルトの振る舞いは、ビューを拡張し、基になるテーブルを使用しようとしていることを前提としています。時には、エンジンの手を持って別の方法で行うように指示する必要があります。そのような明示的なクエリとテーブルのヒントが存在する理由です。 –

+0

ありがとうございます。私はこれについてもっと詳しく説明しますが、これは正しい答えです。 –

関連する問題