【问题标题】:Prevent query rewriting in SQL Server防止 SQL Server 中的查询重写
【发布时间】:2011-01-17 11:01:13
【问题描述】:

我有一列 TypeCode varchar(20),它的值有“1”、“2”、“3”、“FOO”、“BAR”。我需要找到小于参数值的最大整数。像这样的:

select max(TypeCode) TypeCode
    from table1 a
    left join table2 b on b.table1id = a.id
        and b.TypeCode not in ('FOO', 'BAR')
    where b.TypeCode < @MaxType

这在大多数情况下都有效,但在某些查询中,SQL Server 决定将其转换为类似的内容(根据查询计划)。

select max(TypeCode) TypeCode
    from table1 a
    left join table2 b on b.table1id = a.id
        and b.TypeCode < @MaxType
        and b.TypeCode not in ('FOO', 'BAR')

该查询显然会产生以下错误:

Conversion failed when converting the varchar value 'FOO' to data type int.

我尝试创建一个不包含“FOO”和“BAR”值的 table2 视图并改为加入该视图,但查询计划仍然相同。

您知道防止优化器更改查询的方法吗?

PS:我知道表的设计不是最好的,但这是一个遗留数据库,我无法更改它。

【问题讨论】:

    标签: sql-server optimization


    【解决方案1】:

    这里真正的问题是您在同一个查询中结合了字符和整数语义。

    我能想到三种可能的解决方案:

    1. @MaxType 参数更改为varchar(9)。如果您只比较一位数字,则按字母顺序是可以的。否则,这将不起作用。

    2. WHERE 语句中使用CASEISNULL(NULLIF(...)) 构造。这会起作用,但它不是 sargable 并且会导致优化器忽略您在类型代码上拥有的任何索引。不太好。

    3. 创建了一个持久的、计算的、可为空的整数列(即TypeCodeID)并将其单独索引。将CASE 作为列的表达式。这将占用一些额外的数据/索引空间,但如果您想要良好的性能,那是最好的方法。然后不用写NOT IN ('Foo', 'Bar'),你可以只写第一个条件(TypeCode &lt; @MaxType),因为FooBarTypeCode 列中的行将在新的NULL 列中具有NULL

    我想还有第四个答案是改变你的设计,如果可能的话,这将是最好的主意。如果一列可以包含字符数据,那么您真的不应该尝试执行数字比较。我强烈怀疑此列中存在字符数据,因为它来自用户并且未正确验证/清理,因此其中包含N/AUnknown 之类的垃圾值。如果是这种情况,您的数据库确实应该强制执行数据完整性,这就是 DBMS 的用途。我知道你说你“不能改变它”,但如果我不建议反对这种危险的做法,我认为这个答案是不完整的。

    【讨论】:

      【解决方案2】:

      没有办法关闭优化器,而且您可能也不想这样做。更好的解决方案可能是修改查询。

      您可能可以使用 CASE 语句来完成这项工作——例如:

      SELECT MAX(TypeCode) TypeCode
      FROM table1 a
          LEFT JOIN table2 b ON b.table1id = a.id
      WHERE CASE WHEN b.TypeCode IN ('FOO', 'BAR') THEN 99999999999 ELSE CAST(b.TypeCode AS int) END < @MaxType
      

      您需要检查它的性能,看看它是否可以接受,但它应该可以工作。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-03-26
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多