私は単純なインデックス付きビューを持っています。それに対してクエリを実行すると、かなり遅いです。まず、スキーマとインデックスを示します。次に、単純なクエリ。最後に、クエリ プランの画面です。
更新: この投稿の下部にあるソリューションの証明。
スキーマ
これはそれがどのように見えるかです:-
CREATE view [dbo].[PostsCleanSubjectView] with SCHEMABINDING AS
SELECT PostId, PostTypeId,
[dbo].[ToUriCleanText]([Subject]) AS CleanedSubject
FROM [dbo].[Posts]
私の udfToUriCleanText
は、さまざまな文字を空の文字に置き換えるだけです。例えば。すべての「#」文字を「」に置き換えます。
次に、これに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は物事を台無しにしていますか? このビューにインデックスを付けたので、それが具体化されると思いました。そのため、その文字列列を計算する必要はありません。
これが役立つ場合は、クエリプランのスクリーンショットを次に示します:-
また、使用しているインデックスに注意してください。なぜそのインデックスを使用しているのですか?
その指数は…
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)
この問題を解決するのを手伝ってくれてありがとう:)