テーブルの1つに約200万行のSQL2008R2データベースがあり、パラメーター化されたSQLを使用するときに特定のクエリのパフォーマンスに苦労しています。
テーブルには、名前を含むフィールドがあります。
[PatientsName] nvarchar NULL,
フィールドには簡単なインデックスもあります。
CREATE NONCLUSTERED INDEX [IX_Study_PatientsName] ON [dbo].[Study]
(
[PatientsName] 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, FILLFACTOR = 90) ON [INDEXES]
GO
Management Studioでこのクエリを実行すると、実行に約4秒かかります。
declare @StudyPatientsName nvarchar(64)
set @StudyPatientsName= '%Jones%'
SELECT COUNT(*) FROM Study WHERE Study.PatientsName like @StudyPatientsName
しかし、このクエリを実行すると、次のようになります。
SELECT COUNT(*) FROM Study WHERE Study.PatientsName like '%Jones%'
実行には0.5秒以上かかります。
実行プランを見ると、パラメーター化されていないクエリは、上記のインデックスを使用してインデックススキャンを実行します。これは明らかに効率的です。パラメータ化されたクエリはインデックスを使用しますが、インデックスに対して範囲シークを実行します。
問題の一部は、主要なワイルドカードを持つことです。先頭のワイルドカードを削除すると、両方のクエリが数分の1秒で返されます。残念ながら、主要なワイルドカードをサポートする必要があります。
問題が発生した場所でパラメーター化されたクエリを実行する自家製のORMがあります。これらのクエリはユーザーからの入力に基づいて実行されるため、パラメーター化されたクエリはSQLインジェクション攻撃などを回避するのに意味があります。パラメータ化されたクエリ関数とパラメータ化されていないクエリを作成する方法があるかどうか疑問に思っていますか?
クエリオプティマイザにヒントを与えるさまざまな方法を調べて、オプティマイザに各クエリのクエリプランをやり直させようとしましたが、パフォーマンスを向上させるものはまだ見つかりませんでした。私はこのクエリを試しました:
SELECT COUNT(*) FROM Study WHERE Study.PatientsName like @StudyPatientsName
OPTION ( OPTIMIZE FOR (@StudyPatientsName = '%Jones%'))
これはこの質問の解決策として言及されましたが、違いはありませんでした。
どんな助けでもいただければ幸いです。