У меня есть база данных SQL 2008 R2 с около 2 миллионами строк в одной из таблиц, и я испытываю трудности с выполнением определенного запроса при использовании параметризованного 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
Когда я выполняю этот запрос в студии управления, выполнение занимает около 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%'
это занимает чуть больше полсекунды, чтобы выполнить.
Глядя на планы выполнения, запрос без параметризации выполняет сканирование индекса с использованием вышеупомянутого индекса, что, очевидно, является эффективным. Параметризованный запрос использует индекс, но выполняет поиск диапазона по индексу.
Часть проблемы связана с символом подстановки. Когда я удаляю подстановочный знак, оба запроса возвращаются за доли секунды. К сожалению, мне нужно поддерживать ведущие символы подстановки.
У нас есть собственный ORM, который выполняет параметризованные запросы, в которых возникла проблема. Эти запросы выполняются на основе ввода от пользователя, поэтому параметризованные запросы имеют смысл избегать таких вещей, как атака с использованием SQL-инъекций. Мне интересно, есть ли способ сделать функцию параметризованного запроса так же, как и не параметризованный запрос?
Я провел некоторое исследование, изучая различные способы предоставления подсказок оптимизатору запросов, пытаясь заставить оптимизатор повторять план запросов для каждого запроса, но пока не нашел ничего, что могло бы повысить производительность. Я пробовал этот запрос:
SELECT COUNT(*) FROM Study WHERE Study.PatientsName like @StudyPatientsName
OPTION ( OPTIMIZE FOR (@StudyPatientsName = '%Jones%'))
, который был упомянут как решение в этом вопросе, но это не имело значения.
Буду признателен за любую помощь.