Вопрос по индексу - PullRequest
0 голосов
/ 31 мая 2011

У меня следующий запрос:

            SELECT 
                  M.Col7,   
                  M.Col8,   
                  M.Col9,   
                      M.Col10   

                FROM    [MyTable] M                    

        WHERE   M.Col1 = COALESCE(@Col1, M.Col1)              
                AND M.Col2 = COALESCE(@Col2, M.Col2)              
                AND M.Col3 = COALESCE(@Col3,              
                                                M.Col3)              
                AND M.Col4 = COALESCE(@Col4,              
                                                 M.Col4)              
                AND M.Col5 = COALESCE(@Col5,              
                                                    M.Col5)              
                AND M.Col6 LIKE COALESCE(@Col6, M.Col6) +'%'

У меня есть объединенный некластеризованный индекс для столбцов col7,8,9,10. Запрос работает нормально, если я удалю предложение where. Но как только я помещаю предложение where, выполнение запроса занимает много времени. В моей таблице 200 строк. Теперь я собираюсь поместить один некластеризованный индекс со столбцами в следующем порядке: Col1,2,3,4,5,6. Правильно ли я делаю это быстро или что должно быть лучшим вариантом для этого?

Ответы [ 4 ]

3 голосов
/ 31 мая 2011

Попробуйте получить индекс покрытия

CREATE INDEX IX_foo ON MyTable
   (Col1,Col2,Col3,Col4,Col5,Col6)
   INCLUDE (Col7,Col8,Col9,Col10)

Другие мысли:

Другое:

  • Что такое кластеризованный индекс и первичные ключи?

Изменить, чтобы объяснить ГДЕ комментарии

WHERE
    M.Col1 = ISNULL(@Col1, M.Col1)
    AND
    ...

ИЛИ

WHERE
    (@Col1 IS NULL OR M.Col1 = @Col1
    AND
    ...
0 голосов
/ 31 мая 2011

Рокки,

Все ответы, данные до сих пор, помогут.Но я должен сказать, что считаю, что проблема глубже, чем отсутствие индекса.

Во-первых, простое предположение, но тот факт, что у вас уже есть 200К строк в таблице, подсказывает мне, что происходит много операций вставки, даже если нет, чтобы запустить функцию над 200К строк будет будьте медленнее и медленнее, чем больше строк вы получите.

Я предлагаю использовать операторы CASE в предложении where.Это исключит вызов FUNCTION , кратный раз для каждой сканируемой строки.Кроме того, он создаст гораздо лучший план выполнения запросов для SQL Server, или, скорее, позволит SQL Server выбрать более оптимальный план , по моему опыту .

Итак, вот модифицированный запрос:

SELECT M.Col7, M.Col8, M.Col9, M.Col10   
FROM [MyTable] M                    
WHERE M.Col1 = CASE WHEN @Col1 IS NULL THEN M.Col1 ELSE @Col1 END
    AND M.Col2 = CASE WHEN @Col2 IS NULL THEN M.Col2 ELSE @Col2 END           
    AND M.Col3 = CASE WHEN @Col3 IS NULL THEN M.Col3 ELSE @Col3 END             
    AND M.Col4 = CASE WHEN @Col4 IS NULL THEN M.Col4 ELSE @Col4 END              
    AND M.Col5 = CASE WHEN @Col5 IS NULL THEN M.Col5 ELSE @Col5 END              
    AND M.Col6 LIKE CASE WHEN @Col6 IS NULL THEN M.Col6 ELSE @Col6 END +'%'

Надеюсь, это поможет.Затем добавьте индекс @ gbn (+1).

0 голосов
/ 31 мая 2011

Индекс покрытия для запроса наподобие @ gbn , предложенный, вероятно, является лучшей идеей.

С другой стороны, индекс покрытия для многих столбцов не является хорошей идеей ...

Я бы попробовал (если это возможно) кластерный индекс для наиболее селективного столбца в предложении WHERE.

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

0 голосов
/ 31 мая 2011

Как и создание индекса покрытия,

CREATE INDEX NC_Col1Col2Col3Col4Col5Col6_I_Col7Col8Col9Col10
   ON MyTable(Col1, Col2, Col3, Col4, Col5, Col6)   
      INCLUDE (Col7, Col8, Col9, Col10)

Я бы провел сравнение с использованием ISNULL() вместо COALESCE() и поместил бы предложение WHERE в форму, доступную для SARG, чтобы можно было использовать индекс, например,

WHERE  (@Col1 IS NULL OR M.Col1 = @Col1)
       AND   -- etc...
...