Оценивается ли короткое замыкание предложения SQL WHERE? - PullRequest
132 голосов
/ 25 апреля 2009

Например:

SELECT * 
FROM Table t 
WHERE @key IS NULL OR (@key IS NOT NULL AND @key = t.Key) 

Если @ ключ равен NULL имеет значение true, @ ключ НЕ равен NULL И @key = t.Key оценивается?

Если нет, то почему бы и нет?

Если да, это гарантировано? Это часть ANSI SQL или это база данных?

Если база данных специфична, SqlServer? Oracle? MySQL?

Ссылка: Оценка короткого замыкания

Ответы [ 14 ]

1 голос
/ 25 июля 2012

Ниже приведен быстрый и грязный тест на SQL Server 2008 R2:

SELECT *
FROM table
WHERE 1=0
AND (function call to complex operation)

Возвращается немедленно без записей. Вид короткого замыкания присутствовал.

Тогда попробовал это:

SELECT *
FROM table
WHERE (a field from table) < 0
AND (function call to complex operation)

зная, что никакая запись не удовлетворяет этому условию:

(a field from table) < 0

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

Надеюсь, это поможет ребятам.

1 голос
/ 25 апреля 2009

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

Бинарные логические операторы являются коммутативными, что означает:

a AND b == b AND a
a OR  b == b OR  a
a XOR b == b XOR a

, поэтому нет гарантии на порядок оценки. Порядок оценки будет определяться оптимизатором запросов.

В языках с объектами могут быть ситуации, когда вы можете писать логические выражения, которые могут быть оценены только с помощью оценки короткого замыкания. Ваша конструкция примера кода часто используется на таких языках (C #, Delphi, VB). Например:

if(someString == null | someString.Length == 0 )
  printf("no text in someString");

Этот пример C # вызовет исключение, если someString == null, потому что он будет полностью оценен. В оценке короткого замыкания, это будет работать каждый раз.

SQL работает только со скалярными переменными (без объектов), которые не могут быть инициализированы, поэтому нет способа записать логическое выражение, которое не может быть оценено. Если у вас есть какое-либо значение NULL, любое сравнение вернет false.

Это означает, что в SQL вы не можете писать выражения, которые оцениваются по-разному в зависимости от использования короткого замыкания или полной оценки.

Если реализация SQL использует оценку короткого замыкания, она может только ускорить выполнение запроса.

0 голосов
/ 12 июня 2015

Очевидно, что сервер MS Sql поддерживает теорию короткого замыкания, чтобы повысить производительность, избегая ненужных проверок,

Пример поддержки:

SELECT 'TEST'
WHERE 1 = 'A'

SELECT 'TEST'
WHERE 1 = 1 OR 1 = 'A'

Здесь первый пример может привести к ошибке: «Преобразование не удалось при преобразовании значения varchar« A »в тип данных int.»

В то время как второе выполняется легко, поскольку условие 1 = 1 оценивается как ИСТИНА, и, таким образом, второе условие вообще не выполняется.

Дальше больше

SELECT 'TEST'
WHERE 1 = 0 OR 1 = 'A'

здесь первое условие будет оценено как ложное, и, следовательно, СУБД перейдет ко второму условию, и вы снова получите ошибку преобразования, как в примере выше.

ПРИМЕЧАНИЕ: Я НАПИСАЛ НЕПРАВИЛЬНОЕ СОСТОЯНИЕ, ТОЛЬКО ДЛЯ РЕАЛИЗАЦИИ ПОГОДЫ СОСТОЯНИЕ ИСПОЛНЕНО ИЛИ КОРОТКОЕ ЗАКЛЮЧЕНИЕ ЕСЛИ ЗАПРОСЫ РЕЗУЛЬТАТОВ В ОШИБКЕ ОЗНАЧАЕТ ИСПОЛНЕННОЕ СОСТОЯНИЕ, КРАТКОЕ ЗАКЛЮЧЕНИЕ ИНОЕ.

ПРОСТОЕ ОБЪЯСНЕНИЕ

Рассмотрим,

WHERE 1 = 1 OR 2 = 2

поскольку первое условие оценивается как ИСТИНА , бессмысленно оценивать второе условие, потому что его оценка по любому значению никак не повлияет на результат, поэтому Sql Server предоставляет хорошую возможность сэкономить время выполнения запроса, пропуская ненужную проверку или оценку условий.

в случае «ИЛИ» , если первое условие оценивается как ИСТИНА вся цепь, соединенная «ИЛИ» , будет считаться оцененной как истинная без оценки др.

condition1 OR condition2 OR ..... OR conditionN

если условие1 оценивается как истинное, все остальные условия оставляются до тех пор, пока условие N будет пропущено. В общих словах при определении первого ИСТИНА все остальные условия, связанные с ИЛИ, будут пропущены.

Рассмотрим второе условие

WHERE 1 = 0 AND 1 = 1

поскольку первое условие оценивается как FALSE бессмысленно оценивать второе условие, потому что его оценка по любому значению это никак не повлияет на результат, поэтому Sql Server снова предоставляет хорошую возможность сэкономить время выполнения запроса, пропуская ненужную проверку или оценку условий.

в случае "И" , если первое условие оценивается как ЛОЖЬ вся цепь, связанная с "И" , будет считаться оцененной как ЛОЖЬ без оценивая других.

condition1 AND condition2 AND ..... conditionN

если условие1 оценено как ЛОЖЬ , остальные условия до тех пор, пока условиеN будет пропущено. В общих словах при определении первого FALSE все остальные условия, связанные с AND , будут пропущены.

ПОЭТОМУ Мудрый ПРОГРАММЕР ДОЛЖЕН ВСЕГДА ПРОГРАММИРОВАТЬ ЦЕПЬ УСЛОВИЙ В ТАКОМ СПОСОБЕ, КОТОРЫЙ МЕНЬШЕ ДОРОГО ИЛИ БОЛЬШЕ УСТРАНЯЮЩЕЕ СОСТОЯНИЕ ПОЛУЧАЕТ ОЦЕНКУ, ИЛИ УСТАНАВЛИВАЙТЕ СОСТОЯНИЕ В ТАКОМ СПОСОБЕ, КОТОРЫЙ МОЖЕТ ПОЛУЧИТЬ МАКСИМАЛЬНУЮ ВЫГОДУ КОРОТКОГО ЗАМЫКАНИЯ

0 голосов
/ 25 мая 2009

Это занимает дополнительные 4 секунды в анализаторе запросов, поэтому, как я вижу, ЕСЛИ даже не закорочен ...

SET @ADate = NULL

IF (@ADate IS NOT NULL)
BEGIN
    INSERT INTO #ABla VALUES (1)
        (SELECT bla from a huge view)
END

Было бы неплохо иметь гарантированный способ!

...