"где (ParamID = @ParamID) ИЛИ (@ParamID = -1)" хорошая практика в выборе SQL - PullRequest
10 голосов
/ 26 февраля 2012

Я использовал для написания SQL-отчетов, таких как

select * from teacher where (TeacherID = @TeacherID) OR (@TeacherID = -1)

читать дальше

и передать значение @TeacherID = -1, чтобы выбрать всех учителей

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

большое спасибо

Ответы [ 3 ]

6 голосов
/ 27 февраля 2012

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

... Если вы не используете SQL 2008 с пакетом обновления 1 (SP1) CU5 и более поздних версий и используете подсказку OPTION (RECOMPILE).См. Условия динамического поиска в T-SQL для полной статьи по теме.

6 голосов
/ 27 февраля 2012

Мы используем это очень ограниченным образом в хранимых процедурах.

Проблема в том, что ядро ​​базы данных не может поддерживать хороший план запросов для него. При работе с большим количеством данных это может оказать серьезное негативное влияние на производительность.

Однако для небольших наборов данных (я бы сказал, менее 1000 записей, но это предположение) это должно быть хорошо. Вам придется тестировать в вашей конкретной среде.

Если это хранимая процедура, вы можете включить что-то вроде опции WITH RECOMPILE, чтобы план регенерировался при каждом выполнении . Это добавляет (немного) время для каждого прогона, но более чем за несколько прогонов может фактически сократить среднее время выполнения. Кроме того, это позволяет базе данных проверять фактический запрос и «короткое замыкание» детали, которые не нужны при каждом вызове.

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


Другой путь, который вы могли бы рассмотреть, - это использовать UNION ALL запросы, а не необязательные параметры. Например:

SELECT * FROM Teacher WHERE (TeacherId = @TeacherID)
UNION ALL
SELECT * FROM Teacher WHERE (@TeacherId = -1)

Это на самом деле выполняет то же самое; однако план запроса кешируется. Мы также использовали этот метод в нескольких местах и ​​увидели улучшения производительности по сравнению с использованием WITH RECOMPILE. Мы делаем это не везде, потому что некоторые из наших запросов чрезвычайно сложны, и я предпочел бы снизить производительность, чем усложнять их.

В конечном счете, вам нужно много тестировать.


Здесь есть вторая часть, которую вы должны пересмотреть. SELECT *. ВСЕГДА желательно на самом деле назвать столбцы, которые вы хотите вернуть и убедиться, что вы только возвращаете те, которые вам действительно нужны. Перемещение данных через границы сети очень дорого, и вы можете получить приличное повышение производительности, просто указав, что именно вы хотите. Кроме того, если то, что вам нужно, очень ограничено, вы можете иногда охватывать индексы , чтобы ядру базы данных даже не приходилось касаться базовых таблиц, чтобы получить нужные вам данные.

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

Если вы действительно беспокоитесь о производительности, вы можете разбить свою процедуру на два разных процесса: один для всех записей и один на основе параметра.

If @TeacherID = -1
   exec proc_Get_All_Teachers
else
   exec proc_Get_Teacher_By_TeacherID @TeacherID

Каждый из них может бытьоптимизируется индивидуально.

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

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