У меня есть эта хранимая процедура в моей базе данных:
ALTER PROCEDURE [dbo].[sp_FTSearchLocation]
@SearchFor nvarchar(200) = null
,@StartRow int
,@EndRow int
AS
BEGIN
SET NOCOUNT ON;
SELECT * FROM (
SELECT TOP (@EndRow)
*, ROW_NUMBER() OVER (ORDER BY Recommendations DESC, CompanyName) AS num
FROM
dbo.cachedSearchTable
WHERE
(
(@SearchFor IS NULL)
OR (CompanyName like '%' + @SearchFor + '%')
OR (Handle like '%' + @SearchFor + '%')
OR (Activity like '%' + @SearchFor + '%')
)
) As a
WHERE num > @StartRow
OPTION (RECOMPILE)
END
dbo.cachedSearchTable
имеет кластерный индекс со столбцами Recommendations DESC, CompanyName
. Других индексов нет. Я думаю, что можно безопасно использовать *
, потому что таблица cachedSearchTable
построена так, чтобы иметь только столбцы, относящиеся к этому запросу.
Для некоторых строк поиска эта процедура выполняется очень быстро. Например, поиск accountants
возвращает менее чем за секунду. Однако другие работают очень медленно: когда @SearchFor
установлен на soup
, для возврата требуется около 6 секунд.
Планы выполнения для каждого из них выглядят одинаково:
Для Accountants
:
ClusteredIndexScan (85%) ->
Segment (15%) ->
ComputeScalar (0%) ->
SequenceProject (0%) ->
Top (0%) ->
Filter (0%) ->
Select (0%).
Для Soup
:
ClusteredIndexScan (95%) ->
Parallelism (Gather Streams) (5%) ->
Segment (0%) ->
ComputeScalar (0%) ->
SequenceProject (0%) ->
Top (0%) ->
Filter (0%) ->
Select (0%).
Однако для accountants
ClusteredIndexScan оценивается в 0,57, а для soup
- 25,34.
Я попытался поместить 3 некластеризованных индекса в таблицу - по одному для каждого из искомых столбцов - но это не помогло.
В моей базе данных много бухгалтеров (~ 4000) и очень немногие с именем "суп" (~ 50). В целом, кажется, что запрос выполняется быстрее всего, когда из множества возможных результатов можно выбрать, и медленнее, когда результатов очень мало.
Как я могу ускорить этот запрос? Замедление скорости записи в таблицу не имеет значения, но применение большего числа индексов, похоже, не помогает. Можете ли вы что-нибудь предложить?