Оптимизация запросов TSQL и др. - PullRequest
0 голосов
/ 12 февраля 2009

Предположим, у меня есть SQL-оператор, подобный следующему, с переменной @FOO, установленной где-то ранее в коде:

SELECT FIELDLIST 
FROM TABLE 
WHERE 
(FIELD = @FOO OR @FOO IS NULL)

Достаточно ли умен оптимизатор запросов, чтобы сначала выполнить вторую сторону ИЛИ (@FOO IS NULL), потому что (другое предположение) быстрее выполнить нулевую проверку, чем сравнение полей?

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

Ответы [ 5 ]

3 голосов
/ 13 февраля 2009

Краткий ответ ...

Да , оптимизатор достаточно умен.

Чем дольше ответ ...

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

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

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

На практике оптимизатор может иногда ошибаться, но в этом конкретном случае - сравнивая переменную с NULL с чтением из таблицы или индекса - я не думаю, что есть большая вероятность того, что это испортится, хотя вы можете захотеть рассмотрите возможность использования OPTION(RECOMPILE) или OPTION(OPTIMIZE FOR ...).

1 голос
/ 13 февраля 2009

По моему опыту, иногда даже быстрее использовать два запроса и "UNION" вместо предложения "OR".

SELECT FIELDLIST 
FROM TABLE 
WHERE 
(FIELD = @FOO)

UNION

SELECT FIELDLIST 
FROM TABLE 
WHERE 
(@FOO IS NULL)

Недостатком этого подхода является дублирование оператора SELECT, но увеличение производительности на 1500% оправдывает его. Конечно, это зависит от структуры базы данных (в моем случае это было довольно плохо, и я не мог ее изменить).

1 голос
/ 12 февраля 2009

Попробуйте протестировать его с предложениями в обратном порядке:

SELECT FIELDLIST 
FROM TABLE 
WHERE 
(@FOO IS NULL OR FIELD = @FOO)

Вы можете обнаружить, что первый тест закорачивает второй, но не наоборот.

0 голосов
/ 12 февраля 2009

Одним из факторов, который может быть здесь задействован, если этот запрос находится внутри sproc, является "анализ параметров". Это может привести к несовместимому времени ответа на запрос. Чтобы исправить это, объявите внутреннюю переменную в вашем sproc и присвойте эту переменную значению параметра, а затем используйте внутреннюю переменную в предложении where или используйте предложение RECOMPILE в своем sproc. Есть много ссылок на эту тему.

0 голосов
/ 12 февраля 2009

Он достаточно умен, чтобы сначала применить более быстрое условие, предполагая, что он может определить, какое сравнение будет быстрее в общем случае. В этом случае проверка NULL почти всегда будет быстрее, потому что она должна сравнивать не более одного байта с каждой стороны выражения и может ее выделить.

...