Хорошо, плохо или безразлично: ГДЕ 1 = 1


14

Учитывая этот вопрос на Reddit, я очистил запрос, чтобы указать, где проблема была в запросе. Сначала я использую запятую, WHERE 1=1чтобы упростить изменение запросов, поэтому мои запросы обычно заканчиваются так:

SELECT 
     C.CompanyName
    ,O.ShippedDate
    ,OD.UnitPrice
    ,P.ProductName
FROM 
               Customers       as C
    INNER JOIN Orders          as O  ON C.CustomerID = O.CustomerID
    INNER JOIN [Order Details] as OD ON O.OrderID    = OD.OrderID
    INNER JOIN Products        as P  ON P.ProductID  = OD.ProductID
Where 1=1
--  AND O.ShippedDate Between '4/1/2008' And '4/30/2008'
    And P.productname = 'TOFU'
Order By C.CompanyName

Кто-то в основном сказал, что 1 = 1, как правило, ленив и плох для производительности .

Учитывая, что я не хочу «преждевременно оптимизировать» - я хочу следовать хорошей практике. Я смотрел на планы запросов раньше, но в основном только для того, чтобы узнать, какие индексы я могу добавить (или настроить), чтобы мои запросы выполнялись быстрее.

Тогда вопрос действительно ... Where 1=1вызывает ли плохие вещи? И если так, как я могу сказать?

Незначительное редактирование: я всегда «предполагал», что 1=1это будет оптимизировано или, в худшем случае, будет незначительным. Никогда не больно подвергать сомнению мантры, такие как «Goto's are Evil» или «Преждевременная оптимизация ...» или другие предполагаемые факты. Не был уверен 1=1 AND, реально ли это повлияет на планы запросов или нет. Как насчет подзапросов? КТР - х? Процедуры?

Я не тот, кто оптимизирует, если в этом нет необходимости ... но если я делаю что-то действительно "плохое", я бы хотел свести к минимуму последствия или изменить их, где это применимо.


2
Нет, не будет. Помимо нескольких микросекунд для оптимизатора, чтобы удалить избыточное условие. Вам лучше сосредоточиться на своих литералах даты, не будучи двусмысленным.
— ypercubeᵀᴹ

Как сказал @ypercube, это не имеет значения. Оптимизатор запросов должен был бы быть частью ****, чтобы такая вещь имела какое-либо значение;)
— Philᵀᴹ

4
Не верь всему, что читаешь на Reddit. Пожалуйста.
— Аарон Бертран

1
@AaronBertrand Я беру все с зерном соли, пока я не испытал это на собственном опыте. Я по-прежнему отвечу на вопрос, который звучит правдоподобно, и посмотрю, есть ли в этом какая-то правда, особенно когда это влияет на мою повседневную работу.
— WernerCD

4
Есть зерна соли, а затем содержание соли во всем океане, сброшенном на верх вашего офисного здания: P
— Philᵀᴹ

Ответы:


13

SQL Server синтаксический анализаторВ оптимизаторе есть функция «Constant Folding», которая исключает тавтологические выражения из запроса.
Если вы посмотрите на план выполнения, нигде в предикатах вы не увидите этого выражения. Это подразумевает, что постоянное свертывание выполняется в любом случае во время компиляции по этой и другим причинам и не влияет на производительность запроса.

См. Сгибание констант и оценку выражений во время оценки мощности для получения дополнительной информации.


Вероятно, это скомпилировано, потому что это известный шаблон для объединения полей.
— Jcolebrand

Нет, он составлен, потому что он тавтологический. Это будет работать так же, как 2736 = 2736, что не так обычно, как 1 = 1. То же самое относится и к противоречиям. В этом случае функция называется «Обнаружение противоречий».
— Спагеттидба

Какая часть «известного шаблона» означает «должно быть 1 = 1»?
— Jcolebrand

9

Добавление избыточного предиката может изменить ситуацию в SQL Server.

В приведенных ниже планах выполнения обратите внимание на @1первый план по сравнению с литералом 'foo'во втором плане.

введите описание изображения здесь

Это указывает на то, что SQL Server рассматривал первый запрос для простой параметризации, чтобы способствовать повторному использованию плана выполнения - однако сравнение двух констант предотвращает это во втором случае.

Список условий, которые препятствуют простой параметризации (ранее известной как автоматическая параметризация), можно найти в Приложении A к Плану Кэширования Технических Документов Microsoft:

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


4

В любой современной СУБД (включая Oracle, Microsoft SQL Server и PostgreSQL - я в этом уверен) это не повлияет на производительность.

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

SELECT 1 FROM empty_table; -- run this 10 000 times.

SELECT 1 FROM empty_table WHERE 1=1; -- run this 10 000 times and compare.

Для меня в PostgreSQL 9.0 это видно только с 10000 итерациями:

filip@srv:~$ pgquerybench.pl -h /var/run/postgresql/ -q "select 1 from never where 1=1" -q "select 1 from never" -i 10000
Iterations: 10000
Query:   select 1 from never where 1=1
Total:   2.952 s
Average: 0.295 ms
Query:   select 1 from never
Total:   2.850 s
Average: 0.285 ms

0

Это может быть «проблемой» для Oracle, когда вы используете параметр базы данных cursor_sharing. Когда для этого параметра установлено значение «force», будут изменены все операторы SQL. Все «константы» в запросах будут заменены переменными связывания (например, 1 =>: SYS_0).

Эта опция была введена для работы с некоторыми ленивыми разработчиками. С другой стороны, это может также навредить другим ленивым разработчикам. Но риск не слишком высок. Начиная с 11g он имеет функцию просмотра переменных привязки.


Можете ли вы уточнить, что «Начиная с 11g он имеет функцию просмотра переменных привязки». средства?
— ypercubeᵀᴹ

@ypercube «Просмотр переменной привязки» означает, что оптимизатор будет наблюдать фактические значения переменных привязки и использовать статистику данных для переоценки и, возможно, регенерации плана выполнения запроса. Я сомневаюсь, что заглядывание окажет какое-либо влияние на обсуждаемую конструкцию, поскольку оно не зависит от статистики данных.
— Mustaccio
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.