質問

単純なインデックス付きビューがあります。これに対してクエリを実行すると、かなり遅いです。まずスキーマとインデックスを示します。次に簡単なクエリです。最後にクエリプランの画面です。

アップデート:この投稿の下部にある解決策の証拠。

スキーマ

これは次のようになります:-

CREATE view [dbo].[PostsCleanSubjectView] with SCHEMABINDING AS
    SELECT PostId, PostTypeId, 
        [dbo].[ToUriCleanText]([Subject]) AS CleanedSubject
    FROM [dbo].[Posts]

私のUDF ToUriCleanText さまざまな文字を空の文字に置き換えるだけです。例えば。すべての「#」文字を「」に置き換えます。

次に、これに 2 つのインデックスを追加しました:-

インデックス

主キーインデックス (つまり、クラスター化インデックス)

CREATE UNIQUE CLUSTERED INDEX [PK_PostCleanSubjectView] ON 
    [dbo].[PostsCleanSubjectView] 
(
    [PostId] ASC
)
WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, 
      SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF,
      ONLINE = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
GO

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

CREATE NONCLUSTERED INDEX [IX_PostCleanSubjectView_PostTypeId_Subject] ON 
    [dbo].[PostsCleanSubjectView] 
(
    [CleanedSubject] ASC,
    [PostTypeId] ASC
)
WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, 
      SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF,
      ONLINE = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
GO

現在、これには約 25,000 行があります。何も大したことはありません。

次のクエリを実行すると、どちらも約 4 秒かかります。なんと?これはそうあるべきです。基本的にインスタントです!

クエリ 1

SELECT a.PostId
FROM PostsCleanSubjectView a 
WHERE a.CleanedSubject = 'Just-out-of-town'

クエリ 2 (別の where 句項目を追加)

SELECT a.PostId
FROM PostsCleanSubjectView a 
WHERE a.CleanedSubject = 'Just-out-of-town' AND a.PostTypeId = 1

私が何を間違ったのでしょうか?UDF がめちゃくちゃにしてるのか?このビューにインデックスを付けたので、それが実現されるだろうと思いました。したがって、その文字列列を計算する必要はありません。

これが役立つ場合は、クエリプランの画面を次に示します:-alt text

また、使用されているインデックスに注目してください。なぜそのインデックスを使用するのでしょうか?

そのインデックスとは…

CREATE NONCLUSTERED INDEX [IX_Posts_PostTypeId_Subject] ON [dbo].[Posts] 
(
    [PostTypeId] ASC,
    [Subject] ASC
)
WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, 
      SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, 
      ONLINE = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
GO

それで、何かアイデアはありますか?

アップデート 1:udf のスキーマを追加しました。

CREATE FUNCTION [dbo].[ToUriCleanText]
(
    @Subject NVARCHAR(300)
)
RETURNS NVARCHAR(350) WITH SCHEMABINDING
AS 
BEGIN
   <snip>
   // Nothing insteresting in here. 
   //Just lots of SET @foo = REPLACE(@foo, '$', ''), etc.
END

更新 2:解決

はい、それはビューでインデックスを使用しておらず、ビューを展開していないことを手動で確認する必要があったためです。サーバーは SQL Server 2008 Standard Edition です。完全な答えは以下の通りです。これがその証拠です、 WITH (NOEXPAND) alt text

この問題の解決を手伝ってくれてありがとう:)

役に立ちましたか?

解決

SQL Server のエディションは何ですか?Enterprise Edition と Developer Edition だけがインデックス付きビューを自動的に使用し、他のエディションはクエリ ヒントを使用してサポートしていると思います。

SELECT a.PostId
FROM PostsCleanSubjectView a WITH (NOEXPAND)
WHERE a.CleanedSubject = 'Just-out-of-town' AND a.PostTypeId = 1

から MSDN のクエリ ヒント (Transact SQL):

インデックス付きビューは、ビューがクエリの SELECT 部分で直接参照されており、 WITH (NOEXPAND) または WITH (NOEXPAND, INDEX(index_value [ ,...n ] ) ) が指定されている場合にのみ展開されません。

他のヒント

実行計画のクエリコードに@記号が表示されます。文字列変数が関係しています。

SQL Serverは、文字列変数の型がインデックス内の文字列列の型と一致しない場合、NASTY動作をします。 SQL Serverは... 列全体をそのタイプに変換し、高速ルックアップを実行し、変換されたインデックスを破棄して、次のクエリ全体を再度実行できるようにします。


Simonはそれを理解しました-しかし、ここにもっと役立つ詳細があります: http:// msdn.microsoft.com/en-us/library/ms187373.aspx

  

インデックス付きビューとベーステーブルの両方に存在する列への参照がクエリに含まれ、クエリオプティマイザーがインデックス付きビューを使用することがクエリの実行に最適な方法であると判断した場合、クエリオプティマイザーはビューのインデックスを使用します。この機能は、インデックス付きビューマッチングと呼ばれ、SQL Server EnterpriseおよびDeveloperエディションでのみサポートされています。

     

ただし、オプティマイザーが一致するインデックス付きビューを考慮するか、NOEXPANDヒントで参照されるインデックス付きビューを使用するには、次のSETオプションをONに設定する必要があります。

つまり、ここで起こっているのは、インデックス付きビューの一致が機能しないということです。 Sql ServerのEnterpriseまたはDeveloperエディションを使用していることを確認してください(可能性が高い)。次に、記事に従ってSETオプションを確認します。

最近、何億ものコール詳細レコードを含む大規模なデータベースを構築しましたが、クエリとビューで使用していた関数をいくつか、永続的な計算列に変換しました。計算列でインデックスを作成できるため、これははるかにうまくいきました。

SQL Enterpriseを使用していなかったので、インデックス付きビューを使用する機会がありませんでした。インデックス付きビューは、UDFの確定的な結果をインデックス化できるはずですか?

where句で比較を行う前に、すべての行に対してその関数を呼び出す必要があると思います。件名を公開し、それに対して直接クエリチェックを実行し、時間の経過を確認します。関数を使用して値を変更し、それをwhere句で使用するたびに、通常、多くの遅延が発生します...

インデックス付きビューを使用することで、どのようなメリットが得られますか?テーブル自体に適切にインデックスを付けることはできませんか?正当な理由がなければ、複雑さが増し、オプティマイザーに柔軟性の低いデータベースオブジェクトをより多く処理するように依頼することになります。

標準インデックスを使用して同じクエリロジックを評価しましたか?

UDFロジックの混合は、物事をさらに混乱させます。

UDFの戻り値を永続化するだけであれば、インデックス付きビューではなく、永続化された計算列を検討してください。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top