Sql server 这需要根据数据更改执行计划。我认为这是核心问题。是的,我明白你的意思,但我仍然认为这是短路——优化器需要能够看到短路的机会。过去我自己也曾对这类事情做过一些测试,这就是我所看到的(没有以这种方式进行优化)。问题是对于或来说,它可以按任何顺序求值,而且它是先

Sql server 这需要根据数据更改执行计划。我认为这是核心问题。是的,我明白你的意思,但我仍然认为这是短路——优化器需要能够看到短路的机会。过去我自己也曾对这类事情做过一些测试,这就是我所看到的(没有以这种方式进行优化)。问题是对于或来说,它可以按任何顺序求值,而且它是先,sql-server,performance,tsql,sql-execution-plan,short-circuiting,Sql Server,Performance,Tsql,Sql Execution Plan,Short Circuiting,这需要根据数据更改执行计划。我认为这是核心问题。是的,我明白你的意思,但我仍然认为这是短路——优化器需要能够看到短路的机会。过去我自己也曾对这类事情做过一些测试,这就是我所看到的(没有以这种方式进行优化)。问题是对于或来说,它可以按任何顺序求值,而且它是先做右边的。@Hogan,我想实际的问题是SQL Server总是做两边的事,并将它们合并在一起,没有意识到左侧可能总是返回“1”,从而使右侧检查变得多余。这是一个限制,即为查询提供一个单一的、非过程性的执行计划,而不是一个可能在运行时删除部分查


这需要根据数据更改执行计划。我认为这是核心问题。是的,我明白你的意思,但我仍然认为这是短路——优化器需要能够看到短路的机会。过去我自己也曾对这类事情做过一些测试,这就是我所看到的(没有以这种方式进行优化)。问题是对于
来说,它可以按任何顺序求值,而且它是先做右边的。@Hogan,我想实际的问题是SQL Server总是做两边的事,并将它们合并在一起,没有意识到左侧可能总是返回“1”,从而使右侧检查变得多余。这是一个限制,即为查询提供一个单一的、非过程性的执行计划,而不是一个可能在运行时删除部分查询执行路径的过程性检查。即使是工会也在工会的各个方面发挥作用,所以我认为它也逃不过这里。带有IF…ELSE…END逻辑的存储过程可能是唯一的答案。这里有一句话需要注意,因为这不是我第一次看到Nigel Ellis聊天记录:聊天记录于2001年11月19日发布到TechNet。2005年发布的QO经历了重大变化,2008年也经历了更多变化。一般来说,Craig博客上的信息要更新得多。我同意——这本身并不是一个捷径问题,而是一个问题,即即使两个标志都设置为1,查询引擎也会发送工作来检查
text1
的值。这是一个索引操作,但如果SmallTable中的所有选定记录都设置了这些标志,则不需要该操作。正如我在其他地方所评论的,我认为查询优化器“不够聪明”,无法避免BigTable.text1上的工作分支,其中SmallTable中的所有记录都不需要文本比较。不幸的是,没有过程/条件查询树操作符。换句话说,并没有操作符会说“如果条件为真,则沿着这条路走,否则这条路走”。查询优化必须创建一个满足所有可能条件的计划,即使是那些概率很低的条件。当存在确定性条件时,查询计划可以执行许多技巧,例如,连接中的两个表与可信的外部关系可能会从计划中完全删除一个表。这就是所有T-SQL技巧的用武之地,比如使用UNION而不是OR。这是一个非常好的评论。我努力表达我的理解力,但这是一个很好的解释。希望自己能从中学到更多!您提到了
BigTable
上的索引扫描,它是一个视图。它是索引视图,还是对基础表执行索引扫描?请把查询计划贴在这里好吗?
SmallTable
   (id int, flag1 bit, flag2 bit)
JoinTable
   (SmallTableID int, BigTableID int)
BigTable
   (id int, text1 nvarchar(100), otherstuff...)
SELECT * FROM
    SmallTable s
    INNER JOIN JoinTable j ON j.SmallTableID = s.ID
    INNER JOIN BigTable b ON b.ID = j.BigTableID
WHERE
    (s.flag1=1 OR b.text1 NOT LIKE 'pattern1%')
    AND (s.flag2=1 OR b.text1 <> 'value1')
SELECT * FROM
    SmallTable s
    INNER JOIN JoinTable j ON j.SmallTableID = s.ID
    INNER JOIN BigTable b ON b.ID = j.BigTableID
WHERE
    (s.flag1=1) AND (s.flag2=1)
 UNION ALL
 SELECT * FROM
    SmallTable s
    INNER JOIN JoinTable j ON j.SmallTableID = s.ID
    INNER JOIN BigTable b ON b.ID = j.BigTableID
WHERE
    (s.flag1=0 AND b.text1 NOT LIKE 'pattern1%')
    AND (s.flag2=0 AND b.text1 <> 'value1')
SELECT * FROM
    SmallTable s
    INNER JOIN JoinTable j ON j.SmallTableID = s.ID
    INNER JOIN BigTable b ON b.ID = j.BigTableID
WHERE
    (s.flag1=1) AND (s.flag2=1)
 UNION ALL
 SELECT * FROM
    SmallTable s
    INNER JOIN JoinTable j ON j.SmallTableID = s.ID
    INNER JOIN BigTable b ON b.ID = j.BigTableID
WHERE EXISTS
    (SELECT 1 from BigTable b
     WHERE   
    (s.flag1=0 AND b.text1 NOT LIKE 'pattern1%')
    AND (s.flag2=0 AND b.text1 <> 'value1')
)
SELECT * FROM
    SmallTable s
    INNER JOIN JoinTable j ON j.SmallTableID = s.ID
    INNER JOIN BigTable b ON b.ID = j.BigTableID
WHERE
    (s.flag1 = 1 and s.flag2 = 1) OR 
    (
       (s.flag1=1 OR b.text1 NOT LIKE 'pattern1%')
       AND (s.flag2=1 OR b.text1 <> 'value1')
    )
SELECT      * 
FROM        (
            SELECT * FROM SmallTable where flag1 <> 1 or flag2 <> 1
            ) s
INNER JOIN  JoinTable j ON j.SmallTableID = s.ID
...