Будет ли сервер SQL достаточно умным, чтобы не выполнять дорогостоящие запросы, если он не нужен? (Короткое замыкание) - PullRequest
0 голосов
/ 23 апреля 2020

So SQL Сервер не имеет явного короткого замыкания, как, например, для операторов if в языках программирования общего назначения.

Итак, рассмотрим следующий макетный запрос:

SELECT * FROM someTable
WHERE name = 'someValue' OR name in (*some extremely expensive nested sub-query only needed to cover 0.01% of cases*)

Допустим, в таблице всего 3 строки, и все они соответствуют name = 'someValue'. Будет ли когда-нибудь выполняться дорогой подзапрос? Допустим, есть 3 миллиона строк, и все, кроме 1, могут быть выбраны с именем = 'someValue', за исключением 1 строки, которую необходимо извлечь с помощью подзапроса. Будет ли когда-нибудь оцениваться подзапрос, если он не нужен?

Если у вас аналогичный реальный случай, можно было бы подождать, пока 0,01% ждут выполнения дорогостоящего подзапроса, прежде чем получить результаты. если результаты извлекаются быстро без подзапроса для 99,99% случаев. (Я знаю, что мой конкретный пример c, приведенный выше, может быть явно обработан с помощью IF-операторов в SP, как предлагается в этом связанном потоке: Sql короткое замыкание ИЛИ или условие существует в предложении where , но давайте предположим, что это не вариант.)

1 Ответ

1 голос
/ 23 апреля 2020

Как отмечается в комментариях, оптимизатор в SQL Сервер довольно умный.

Вы можете попытаться замкнуть накоротко, используя case. Поскольку документация гласит:

Выражение CASE последовательно оценивает свои условия и останавливается на первом условии, условие которого выполнено.

Обратите внимание, что есть некоторые исключения, связанные с агрегацией. Итак, вы можете сделать:

SELECT t.*
FROM someTable t
WHERE 'true' = (CASE WHEN t.name = 'someValue' THEN 'true'
                     WHEN t.name in (*some extremely expensive nested sub-query only needed to cover 0.01% of cases*)
                     THEN 'true'
                END)

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

В вашем случае, я подозреваю, что замена IN с EXISTS и использование соответствующих индексов может устранить почти все потери производительности подзапроса. Однако это другое дело.

...