Хорошо, плохо или безразлично: ГДЕ 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, реально ли это повлияет на планы запросов или нет. Как насчет подзапросов? КТР - х? Процедуры?

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

WernerCD
источник
2
Нет, не будет. Помимо нескольких микросекунд для оптимизатора, чтобы удалить избыточное условие. Вам лучше сосредоточиться на своих литералах даты, не будучи двусмысленным.
ypercubeᵀᴹ
Как сказал @ypercube, это не имеет значения. Оптимизатор запросов должен был бы быть частью ****, чтобы такая вещь имела какое-либо значение;)
Philᵀᴹ
4
Не верь всему, что читаешь на Reddit. Пожалуйста.
Аарон Бертран
1
@AaronBertrand Я беру все с зерном соли, пока я не испытал это на собственном опыте. Я по-прежнему отвечу на вопрос, который звучит правдоподобно, и посмотрю, есть ли в этом какая-то правда, особенно когда это влияет на мою повседневную работу.
WernerCD
4
Есть зерна соли, а затем содержание соли во всем океане, сброшенном на верх вашего офисного здания: P
Philᵀᴹ

Ответы:

13

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

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

spaghettidba
источник
Вероятно, это скомпилировано, потому что это известный шаблон для объединения полей.
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
filiprem
источник
0

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

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

ibre5041
источник
Можете ли вы уточнить, что «Начиная с 11g он имеет функцию просмотра переменных привязки». средства?
ypercubeᵀᴹ
@ypercube «Просмотр переменной привязки» означает, что оптимизатор будет наблюдать фактические значения переменных привязки и использовать статистику данных для переоценки и, возможно, регенерации плана выполнения запроса. Я сомневаюсь, что заглядывание окажет какое-либо влияние на обсуждаемую конструкцию, поскольку оно не зависит от статистики данных.
Mustaccio