Как оценивается оператор SQL OR - PullRequest
0 голосов
/ 27 января 2011

Система: SQL Server 2008-R2

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

Когда я делаю:

SELECT XXXXX
FROM   YYYYY
WHERE ( ------------ ) AND 
      (Level >= @MinLevel) AND
      ( ------------ )

Я получил правильный ответ.

В попытке оптимизировать запрос я попытался сделать:

SELECT XXXXX
FROM   YYYYY
WHERE ( ------------ ) AND 
      ((@MinLevel = 0) OR (Level >= @MinLevel)) AND
      ( ------------ )

Если запрошенный минимальный уровень равен 0, нет необходимости добавлять минимальный ограничение уровня запроса и тем самым сохранить оператор сравнения для операции (при условии, что на уровне нет индекса)

На самом деле я получил более длинный запрос или, по крайней мере, не более короткий запрос, чем «неоптимизированный».

Может кто-нибудь объяснить, почему?

Ответы [ 3 ]

2 голосов
/ 27 января 2011

Вопрос sql-server-2008-r2, поэтому мы не будем рассматривать другие СУБД.

Посмотрите здесь для более глубокого анализа: http://www.sommarskog.se/dyn-search-2008.html

В нем рассматриваютсямного способов выполнить динамический поиск, который в некоторой степени относится к вопросу.В частности, эта цитата:

Эффект всех предложений @x IS NULL заключается в том, что если этот входной параметр равен NULL, то условие AND всегда выполняется. Таким образом, действуют только те условия, в которых параметр поиска имеет ненулевое значение.

.... А производительность? Очень хорошо, если вы включите в запрос подсказку OPTION (RECOMPILE).

Это найдено в разделе Static SQL и относится к SQL 2008 R2 CU1 (10.50.1702) or later.

Тот же ярлык оптимизации (оценивать RHS, только когда (@MinLevel = 0)) применяется к вашему запросу с подсказкой OPTION (RECOMPILE).

(заметил, что это было предложено вкомментарий против вопроса)

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

Оператор ИЛИ обычно выбрасывает индексирование в окно.

Представьте, что у вас есть таблица с индексированным столбцом идентификаторов, который считает один раз на строку.В этой таблице у вас есть 100 строк.Строка 1 будет иметь значение 1 в этом столбце, а строка 100 будет иметь значение 100.

Теперь выполните этот запрос: SELECT * FROM таблицы WHERE столбец> = 45

Этот запрос имеет определенную начальную точку: 45

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

Короче говоря, чтобы найти первое45, он должен смотреть только на 6-7 строк.Затем он возвращает каждую строку оттуда до конца таблицы в качестве набора результатов.

Теперь давайте настроим этот запрос следующим образом: SELECT * FROM таблицы WHERE column> = 45 OR column = 43

У нас больше нет определенной начальной точки.База данных не может определить одну конкретную строку для запуска ваших результатов.Чтобы определить, какие записи возвращать, необходимо проверить каждую строку , чтобы убедиться, что она соответствует вашим требованиям.Если он совпадает, он добавляет эту строку к своим результатам и переходит к следующей.

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

Предложение OR не оптимизировано (почти во всех СУБД). Например, это означает, что индекс будет игнорироваться, и оба случая должны быть оценены.

Прямое> = просто прямое сравнение

...