【问题标题】:Select statement processing before Where clause in view视图中Where子句前的select语句处理
【发布时间】:2012-03-15 03:16:13
【问题描述】:

我有一个选择 charindex 的子字符串的语句,如下所示:

SELECT SUBSTRING(StringField, 5, CHARINDEX('ABC', StringField) - 5)...
WHERE 
CHARINDEX('ABC', StringField) > 5

当我在选择查询中运行上述语句时,结果返回得很好。当我在模式绑定索引视图中运行上述语句时,我收到此错误:

Invalid length parameter passed to the LEFT or SUBSTRING function

为了解决这个问题,我将编写一个函数来获取 CharIndex 的最大值和 0,以消除负值的可能性。但是有谁知道为什么 where 子句不会过滤掉 select 语句?

【问题讨论】:

    标签: sql database database-indexes


    【解决方案1】:

    因为无法保证查询中幕后的操作顺序。

    我猜如果您检查执行计划,您会看到它同时执行两项检查 - 这是因为两个操作都不能使用索引!

    无论如何,SQL 都需要将该字段的每一行加载到内存中,因此它同时针对这两个条件进行处理。

    您可以尝试WITH (MAXDOP(1)) 作为查询提示,看看是否会阻止问题出现,或者您可以进行子选择以强制执行顺序:

    SELECT SUBSTRING(StringField, 5, CHARINDEX('ABC', StringField) - 5)...
    FROM (
          SELECT Stringfield 
          FROM Table 
          WHERE CHARINDEX('ABC', StringField) > 5
          ) as [X]
    

    当我使用PATINDEX 检查字段是否为数字时,我遇到了类似的问题,并且我视图中的一列将其转换为int - 因为引擎正在转换,所以出现转换错误自从我的过滤器不是 SARGable 以来的每一行。

    【讨论】:

    • 顺便说一句,Jonathan Kehayias 报告说他看到了即使是子查询或 CTE 也无法帮助优化器的情况,并且处理仍然可以反过来进行。在这些情况下,唯一的解决方法是找出一个不这样做的计划并使用固定计划,或者首先将子查询转储到 #temp 表以确保首先发生过滤。
    【解决方案2】:

    这是一个丑陋的解决方法,但您也许可以这样做:

    DECLARE @x TABLE(StringField VARCHAR(32));
    
    INSERT @x SELECT 'ABC'
    UNION ALL SELECT 'A'
    UNION ALL SELECT 'AAAAAAAABC';
    
    SELECT SUBSTRING(StringField, 5, CHARINDEX('ABC', StringField) - 5)
    FROM @x
    WHERE CHARINDEX('ABC', StringField) > 5;
    
    SELECT SUBSTRING(StringField,
        CASE WHEN CHARINDEX('ABC', StringField) > 5 THEN 5 ELSE 1 END,
        CHARINDEX('ABC', StringField) - 
        CASE WHEN CHARINDEX('ABC', StringField) > 5 THEN 5 ELSE 0 END)
    FROM @x
    WHERE CHARINDEX('ABC', StringField) > 5;
    

    两者都有:

    ---
    AAA
    

    但我怀疑您认为后者会被允许。这很难看,但不幸的是,除非您首先将过滤后的数据转储到 #temp 表(或尝试查看 MAXDOP 是否可靠地消除了该问题),否则您将无法控制处理顺序。

    另一个想法是尝试将计算列放入表中(但我不确定如果您尝试创建索引视图是否会有所帮助 - 可能仍然存在并发症)。或者使用带有该表达式的过滤索引,而不是索引视图。如果我们知道索引视图的目的是什么以及您使用的是什么版本的 SQL Server,那么可能会有几个“解决方案”。

    【讨论】:

    • (顺便说一句,SQL Server 足够聪明,每行只执行一次计算机标量运算符,所以不要认为那些额外的 charindex 操作对计划、持续时间、CPU 等有任何影响.)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-12-07
    • 1970-01-01
    • 2018-04-16
    • 2023-03-15
    • 2011-09-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多