Добавление дополнительного предложения Where в SQL приводит к значительному снижению производительности - PullRequest
2 голосов
/ 21 января 2011

У меня есть SQL-запрос, который проходит через несколько представлений и таблиц.

Запрос выполняется нормально, но когда я добавил еще одно условие в предложение WHERE, он начал оказывать огромное влияние на производительность.

Запрос структурирован как ...

         SELECT a.*
           FROM vw_myView a
LEFT OUTER JOIN tbl1 b ON a.ID = b.ID
LEFT OUTER JOIN vw_OtherView c ON a.ID = c.ID
LEFT OUTER JOIN tbl2 d ON c.OtherID = d.OtherID
          WHERE a.Column1 = 'VALUE'
            AND a.Column2 LIKE ISNULL(@parameter, a.Column2)

Из приведенного выше запроса, когда я добавляю другое условие в предложение WHERE, мой запрос теперь занимает много времени (более 3 минут)) выполнить и вернуть 1000 записей.Удаление добавленного условного предложения и запроса возвращает записи менее чем за 7 секунд.

Спасибо.Что я должен проверить, чтобы увидеть, где производительность огромна

Ответы [ 5 ]

1 голос
/ 21 января 2011

Посмотрите на план выполнения вашего запроса .Ставлю доллары на пончики, что ваш дополнительный поисковый аргумент вызывает сканирование таблицы, очень дорогая процедура с точки зрения производительности.

0 голосов
/ 21 января 2011

попробуйте это.

AND (a.Column2 = @parameter OR @parameter is NULL)

Не понимаю, почему вы используете как?

Вы хотите сделать что-то подобное

AND (a.Column2 like @parameter+'%' OR @parameter is NULL)
0 голосов
/ 21 января 2011

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

Поскольку у вас есть только два условия, я мог бы попытаться написать это так: IF @parameter IS NULL

BEGIN
    SELECT a.*            
    FROM vw_myView a 
    LEFT OUTER JOIN tbl1 b 
    ON a.ID = b.ID 
    LEFT OUTER JOIN vw_OtherView c 
    ON a.ID = c.ID 
    LEFT OUTER JOIN tbl2 d ON c.OtherID = d.OtherID           
    WHERE a.Column1 = 'VALUE'             
    AND a.Column2 LIKE a.Column2 
END
ELSE 
BEGIN
    SELECT a.*            
    FROM vw_myView a 
    LEFT OUTER JOIN tbl1 b 
    ON a.ID = b.ID 
    LEFT OUTER JOIN vw_OtherView c 
    ON a.ID = c.ID 
    LEFT OUTER JOIN tbl2 d ON c.OtherID = d.OtherID           
    WHERE a.Column1 = 'VALUE'             
    AND a.Column2 LIKE  @parameter
END

Конечно, вы никогда не должны использовать SELECT * в рабочем коде и использовать =, если возможно, вместо LIKE. И если эти представления ссылаются на одни и те же таблицы, непосредственный запрос таблиц может быть лучшим выбором для повышения производительности.

0 голосов
/ 21 января 2011

Ваше условие запроса AND a.Column2 LIKE ISNULL(@parameter, a.Column2) включает вызов функции, поэтому SQL Server должен выполнить сканирование таблицы (т. Е. Проверить эту функцию по каждой строке) в вашей таблице, чтобы убедиться,он удовлетворяет запросу.

Даже если у вас есть индекс на a.Column2, Sql Server не сможет его использовать.

[EDIT] Это один из способов ускоренияэто в большинстве случаев

-- Only this part executes when the @parameter has a value.
-- It returns nothing and executes fast when @parameter is NULL

SELECT a.*
           FROM vw_myView a
LEFT OUTER JOIN tbl1 b ON a.ID = b.ID
LEFT OUTER JOIN vw_OtherView c ON a.ID = c.ID
LEFT OUTER JOIN tbl2 d ON c.OtherID = d.OtherID
          WHERE a.Column1 = 'VALUE'
            AND a.Column2 LIKE @parameter

UNION ALL

-- This part does not execute when the @paramter has a value
-- This will leave the 2nd query clause out and run faster when @parameter is not specified, avoiding a table scan

SELECT a.*
           FROM vw_myView a
LEFT OUTER JOIN tbl1 b ON a.ID = b.ID
LEFT OUTER JOIN vw_OtherView c ON a.ID = c.ID
LEFT OUTER JOIN tbl2 d ON c.OtherID = d.OtherID
          WHERE a.Column1 = 'VALUE'
            AND @parameter IS NULL
0 голосов
/ 21 января 2011

Зачем это? AND a.Column2 LIKE ISNULL(NULL, a.Column2)
Это всегда собираюсь проверить a.Column2 LIKE a.Column2
Вы пытаетесь просто проверить a.Column2 IS NULL?

Можете ли вы опубликовать запрос, как он был до изменения?

[Изменить]
Я не знаю вашу целевую базу данных, но если это Sybase, я бы предостерег вас от использования @parameter + '%', который будет выполнять сканирование таблицы Вы можете прочитать больше на Нравится или не нравится .

...