繁体   English   中英

SQL Server视图执行计划:是在哪里还是与UNION相同?

[英]SQL Server View Execution Plan: Is WHERE OR the Same as UNION?

我认为这是联接的集合。 出于这个问题的目的,我将简化以下观点。 注意, Table1.Table1ID是主键, Table2.Table1ID是外键。

CREATE VIEW [View1] AS
SELECT t1.Column1, t2.Column2
FROM Table1 t1
JOIN Table2 t2 ON t1.Table1ID = t2.Table1ID

为此使用视图非常好,因为它减少了我在代码中必须执行的联接数量,并且允许SQL Server更有效地优化联接。 例如:

SELECT Column1, Column2
FROM View1
WHERE Column1 = 'abc'
AND Column2 = 'xyz'
GROUP BY Column1, Column2

SQL Server通过仅联接来自Table1的记录子集(其中Column1中的值为“ abc”)和来自Table2的记录子集(其中Column2中的值为“ xyz”)来优化上述查询。 换句话说,SQL Server执行计划在应用联接之前将筛选巧妙地应用于视图中的各个表,从而减少了联接中需要考虑的记录数。

但是,如果我改变通过改变前查询AND运营商在WHERE子句中的OR操作,执行计划执行联接之前应用的筛选。

SELECT Column1, Column2
FROM View1
WHERE Column1 = 'abc'
OR Column2 = 'xyz'
GROUP BY Column1, Column2

上面查询的执行计划首先连接Table1和Table2中的所有记录,然后再应用where子句。 这符合布尔逻辑,因为在连接表并且同时存在并考虑Column1和Column2中的值之前,不能满足OR运算符测试。

另一方面,以下查询返回与前一个查询相同的结果集。

SELECT Column1, Column2
FROM View1
WHERE Column1 = 'abc'
UNION
SELECT Column1, Column2
FROM View1
WHERE Column2 = 'xyz'

后两个查询产生相同的结果,但是两个查询中的第二个由SQL Server优化,以便执行计划在联接中拆分视图之前将where子句应用于各个SELECT语句中的各个表,从而减少了查询记录被加入。 即使实际上两次调用了该视图,并且UNION返回了结果记录集的交集,这也会导致总体上更高效的查询。

我的问题是:

  • 为什么SQL Server不使用类似于上一个查询的执行计划来优化倒数第二个查询?
  • 有没有一种方法可以定义视图,以便SQL Server使用类似于上一个查询的执行计划对其进行优化?

谢谢。

为什么SQL Server不使用类似于上一个查询的执行计划来优化倒数第二个查询?

它可以进行与您提供的示例相似的转换。 您需要计算Remus答案中提到的细节。 我很确定这是可行的。 例如,您可以使用可以将UNION重写为FULL OUTER JOIN的事实。 这样就可以插入正确的重复数据删除条件。

截至2012年,该转换尚未实现。这是不幸的,但是产品团队仍然无法提供理想的优化器。 我们拥有的相当不错。

有没有一种方法可以定义视图,以便SQL Server使用类似于上一个查询的执行计划对其进行优化?

从来没听说过。

我知道这个答案并不能改善您的情况,但事实就是如此。 现在,考虑创建索引视图。 这样,您可以预生成您感兴趣的行的子集。您可以创建跨多个表的列的索引。 您可以索引表达式。

WHERE ... OR ...是与UNION不同的查询。 如果单行出现值abcColumn1xyzColumn2会产生只有一个行WHERE ... OR ...如此,但在两行UNION情况。 您可能会说UNION删除重复项(因为不是UNION ALL ),我说这是一个简化的示例,它忽略了其他正在投影的列。 但即使考虑到这个例子广告literam然后我就可以给其中行的值分别为另一种情况abcColumn1xyzColumn2 ,而第二个返回1 QED,优化你期望,在这种情况下,第一个查询返回两行,不能发生是因为不正确。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM