2013-06-06 3 views
1

У меня есть приложение, в котором пользователь имеет маску, которая запускает операторы sql в базе данных SQL Server 2008. Кроме того, пользователь может устанавливать параметры в маске. Рассмотрим маску с одним параметром, который представляет собой раскрывающийся список с двумя вариантами: «Самолеты» и «Автомобили».SQL Server 2008: оптимизация производительности запроса с известным пустым результатом

Когда пользователь выбирает «Автомобили» и нажимает кнопку «Выполнить», следующий запрос SQL, который я сконфигурировал ранее в маске, попадает в базу данных.

SELECT cars.id, cars.name 
FROM cars 
WHERE 'Cars' = 'Cars' 

UNION ALL 

SELECT planes.id, planes.name 
FROM planes 
WHERE 'Planes' = 'Cars' 

(Это довольно составлен пример, так как запросы в моей заявке являются гораздо более сложными с большим количеством JOINS и так далее ...)

Даже если я возьму вторую часть и вставить его в студию управления SQL Server, установите некоторые параметры и нажмите «выполнить», запрос займет несколько секунд, чтобы завершить ... с пустым результатом.

Мой вопрос сейчас: как я могу оптимизировать вторую часть, поэтому SQL Server распознает, что во втором операторе SELECT действительно нечего делать?

EDIT:

Причина, почему мой второй («мертвые») запрос выполняется в течение некоторого времени, заключается в следующем: В запросе есть JOINS, наряду с Sub-SELECT в ИНЕКЕ. Скажем,

SELECT planes.id, planes.name 
FROM planes 
INNER JOIN very_complex_colour_view colours 
    ON colours.id = planes.colour.id 
WHERE 'Planes' = 'Cars' 

Фактически даже таблица «плоскостей» представляет собой сложный вид.

+0

Не можете ли вы использовать [IN] (http://msdn.microsoft.com/en-us/library/ms177682.aspx) в своем запросе? – acermate433s

ответ

1

В зависимости от параметра он выбирает записи из соответствующей таблицы. Так что не нужно использовать UNION ALL.

Использование IF ELSE конструкт -

DECLARE @Input VARCHAR(20) = 'Cars' 

IF (@Input = 'Cars') 
BEGIN 
    SELECT cars.id, cars.name 
    FROM cars 
END 
ELSE IF (@Input = 'Planes') 
BEGIN 
    SELECT planes.id, planes.name 
    FROM planes 
END 

Это также поможет SQL Optimizer использовать Parameter Sniffing технику и использовать наилучший план выполнения, который позволит улучшить производительность запросов.

Подробнее о Parameter Sniffing -

+0

Я пробовал ваше решение, второй запрос в конструкции if (1 = 2) ..., к сожалению, это не решило проблему. Посмотрите на параметр sniffing, спасибо за подсказку! – curmudgeon

+0

@curmudgeon, почему это не сработало? он даже не попадет в таблицу 'planes', если вы передаете параметр как' Cars'. Я считаю, что ваш запрос немного сложнее, чем проблема. –

+0

@curmudgeon вы можете поместить некоторый код с количеством фиктивных таблиц? Я думаю, вам нужно использовать 'EXISTS' в' if' для проверки. Я мог только догадываться, пока вы не надели какой-то код. –

0

Когда я запускаю следующий запрос в моей системе:

select * 
from <really big table that is not in the cache> 
where 'planes' = 'cars' 

результаты возвращаются в примерно 1 секунду первый раз и последующие LY.

Я подозреваю, что ваш фактический запрос более сложный, чем этот пример. И упрощение устраняет проблему. Даже когда я пытаюсь выполнить вышеперечисленное с присоединением, в целом нет никакого хита производительности.

Основываясь на планах выполнения, которые я вижу, SQL Server признает, что константа всегда ложна. Следующий запрос:

select * 
from Published_prev2..table1 sv join 
    Published_prev2..table2 sl 
    on sv.id= sl.id 
where 'planes' = 'cars' 

Производит постоянное сканирование плана выполнения.Тот же запрос с 'cars = cars' создает более сложный план, который имеет соединения и так далее.

Смежные вопросы