代码之家  ›  专栏  ›  技术社区  ›  Adrian Godong

T-SQL 1=1性能命中率

  •  17
  • Adrian Godong  · 技术社区  · 17 年前

    对于SQL查询,我通常对SELECT语句执行以下操作:

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

    如果我需要添加/删除/注释任何WHERE子句,这将很容易,因为我不必关心第一行。

    其他信息:

    例如,绵羊模仿者和所有其他未获得使用权的人。

    假设上面的查询,我需要将@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
    ...
    
    8 回复  |  直到 17 年前
        1
  •  20
  •   Steve Horn    15 年前

    不,SQL Server足够聪明,可以从执行计划中省略此条件,因为它总是 TRUE

    Oracle、MySQL和PostgreSQL也是如此。

        2
  •  14
  •   TheTXI    17 年前

    很可能,如果您使用探查器并查看,您最终会发现优化器往往会忽略这一点,因此在总体方案中,可能不会有太多的性能增益或损失。

        3
  •  4
  •   Remus Rusanu    17 年前

        4
  •  2
  •   Cade Roux    17 年前

    没有区别,因为它们评估了常数并进行了优化。我在手动和生成的代码中都使用1=1和0=1 AND OR

        5
  •  2
  •   adrianbanks    17 年前

    由于该条件始终为true,SQL Server将忽略它。您可以通过运行两个查询进行检查,一个带条件,一个不带条件,并比较两个实际执行计划。

    要满足您的评论要求,另一种方法是重新构造查询:

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

    然后,您可以在where条件中添加/删除/注释掉行,它仍然是有效的SQL。

        6
  •  2
  •   Martin Smith    11 年前

    一个潜在的轻微负面影响是 AND 1=1 将停止SQL Server的 simple parameterisation 防止踢进。

    演示脚本

    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 满足于缓存计划的单个参数化版本,而 编译并存储不同常量值的单独计划。

    enter image description here

    理想情况下,无论如何都不应该依赖于此,应该显式地对查询进行参数化,以确保所需的元素已参数化,并且参数具有正确的数据类型。

        7
  •  1
  •   p.campbell    17 年前

    最好的情况是进行一点一点的比较。更糟糕的情况是,数字被计算为整数。

        8
  •  1
  •   A-K    17 年前

    对于任何合理复杂度的查询,都没有区别。您可以查看一些执行计划,也可以比较实际的执行成本,自己看看。