Подтвердить что ты не робот

T-SQL 1 = 1 Производительность

Для моих SQL-запросов я обычно делаю следующее для операторов SELECT:

SELECT ...
FROM table t
WHERE 1=1
  AND t.[column1] = @param1
  AND t.[column2] = @param2

Это упростит, если мне нужно добавить/удалить/комментировать любые предложения WHERE, так как мне не нужно заботиться о первой строке.

Есть ли какая-либо производительность при использовании этого шаблона?

Дополнительная информация:

Пример для sheepsimulator и всех других, кто не получил использования.

Предположим, что для этого запроса мне нужно изменить @param1, чтобы он не был включен в запрос:

С 1 = 1:

...
WHERE 1=1 <-- no change
  --AND t.[column1] = @param1 <-- changed
  AND t.[column2] = @param2 <-- no change
...

Без 1 = 1:

...
WHERE <-- no change
  --t.[column1] = @param1 <-- changed
  {AND removed} t.[column2] = @param2 <-- changed
...
4b9b3361

Ответ 1

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

Ответ 2

Нет, SQL Server достаточно умен, чтобы исключить это условие из плана выполнения, поскольку он всегда TRUE.

То же самое верно для Oracle, MySQL и PostgreSQL.

Ответ 3

Это не влияет на производительность, но там текст SQL выглядит так, будто он искажен атакой SQL-инъекции. Трюк "1 = 1" появляется во многих атаках на основе инъекций на основе sql. Вы просто рискуете, что какой-то ваш клиент когда-нибудь развернет "черный ящик", который контролирует трафик SQL, и вы обнаружите, что ваше приложение помечено как "взломанный". Это могут указывать и анализаторы исходного кода. Конечно, это длинный выстрел, но что-то стоит положить в равновесие.

Ответ 4

Нет никакой разницы, поскольку они оценивали константы и оптимизировались. Я использую как 1 = 1, так и 0 = 1 как в списках AND, так и в коде OR сгенерированных кодом и кодом, и он не имеет эффекта.

Ответ 5

Так как условие всегда верно, SQL Server игнорирует его. Вы можете проверить, выполнив два запроса, один с условием и один без, и сравнив два фактических плана выполнения.

Альтернативой вашей легкости комментирования является реструктуризация вашего запроса:


SELECT ...
FROM table t
WHERE 
    t.[column1] = @param1 AND
    t.[column2] = @param2 AND
    t.[column3] = @param3

Затем вы можете добавлять/удалять/прокомментировать строки в тех условиях, где он будет, и он будет по-прежнему действительным SQL.

Ответ 6

Не удавалось достичь производительности. Даже если ваше предложение WHERE загружено большим количеством сравнений, это крошечно.

Лучший сценарий - это сравнение бит-бит. Хуже того, цифры считаются целыми числами.

Ответ 7

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

Ответ 8

Одним из потенциально незначительно негативных последствий этого является то, что AND 1=1 остановит запуск SQL Server простой параметризации.

Демо script

DBCC FREEPROCCACHE;  /*<-- Don't run on production box!*/

CREATE TABLE [E7ED0174-9820-4B29-BCDF-C999CA319131]
(
X INT, 
Y INT,
PRIMARY KEY (X,Y)
);

GO
SELECT *
FROM   [E7ED0174-9820-4B29-BCDF-C999CA319131]
WHERE  X = 1
       AND Y = 2;
GO
SELECT *
FROM   [E7ED0174-9820-4B29-BCDF-C999CA319131]
WHERE  X = 2
       AND Y = 3;
GO   
SELECT *
FROM   [E7ED0174-9820-4B29-BCDF-C999CA319131]
WHERE  1 = 1
       AND X = 1
       AND Y = 2 
GO   
SELECT *
FROM   [E7ED0174-9820-4B29-BCDF-C999CA319131]
WHERE  1 = 1
       AND X = 2
       AND Y = 3    

SELECT usecounts,
       execution_count,
       size_in_bytes,
       cacheobjtype,
       objtype,
       text,
       creation_time,
       last_execution_time,
       execution_count
FROM   sys.dm_exec_cached_plans a
       INNER JOIN sys.dm_exec_query_stats b
         ON a.plan_handle = b.plan_handle
       CROSS apply sys.dm_exec_sql_text(b.sql_handle) AS sql_text
WHERE  text LIKE '%\[E7ED0174-9820-4B29-BCDF-C999CA319131\]%' ESCAPE '\'
       AND text NOT LIKE '%this_query%'
ORDER BY last_execution_time DESC       

GO

DROP TABLE [E7ED0174-9820-4B29-BCDF-C999CA319131]   

Показывает, что оба запроса без 1=1 удовлетворялись одной параметризованной версией кэшированного плана, тогда как запросы с помощью 1=1 скомпилировали и сохранили отдельный план для разных постоянных значений.

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

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