ВЫБРАТЬ Скорость запроса сильно зависит от разных входов? - PullRequest
1 голос
/ 15 февраля 2012

У меня есть эта хранимая процедура в моей базе данных:

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). В целом, кажется, что запрос выполняется быстрее всего, когда из множества возможных результатов можно выбрать, и медленнее, когда результатов очень мало.

Как я могу ускорить этот запрос? Замедление скорости записи в таблицу не имеет значения, но применение большего числа индексов, похоже, не помогает. Можете ли вы что-нибудь предложить?

1 Ответ

3 голосов
/ 15 февраля 2012

Поиск по LIKE %something принесет , а не выгоду от индекса B-дерева. Тот факт, что поиск занимает только 4000 строк (а не миллисекунд), является дополнительным указанием на то, что это так. Не смущайтесь ClusteredIndexScan в вашем плане запросов - это просто кластеризованный эквивалент полного сканирования таблицы.

Итак, почему разница? Поскольку существует еще accountants, а затем soup с, и вы ищете только TOP N строк, первый запрос будет стремиться найти N строк раньше, чем второй, т. Е. Сканируя меньшую часть таблицы.

Вам нужно будет либо переписать запрос, чтобы использовать LIKE something%, либо (если возможно) использовать полнотекстовое индексирование.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...