假设你有一个观点:
CREATE VIEW dbo.v_SomeJoinedTables AS
SELECT
a.date,
a.Col1,
b.Col2,
DENSE_RANK()
OVER(PARTITION BY a.date, a.Col2 ORDER BY a.Col3) as Something
FROM a JOIN b on a.date = b.date
我发现了以下的表现:
SELECT *
FROM v_SomeJoinedTables
WHERE date > '2011-01-01'
比
更糟糕SELECT *,
DENSE_RANK()
OVER(PARTITION BY a.date, a.Col2 ORDER BY a.Col3) as Something
FROM a JOIN b ON a.date = b.date
WHERE a.date > '2011-01-01'
我很惊讶这两个语句的查询计划不一样。
我也尝试使用内联表值函数,但查询仍然比我复制和粘贴视图逻辑的代码长100-1000倍。
有什么想法吗?
答案 0 :(得分:16)
它被称为“Predicate pushing”又称延迟过滤。
SQL Server并不总是能够有效地在视图内部“更早地”应用WHERE。
在SQL Server 2008中已经减轻了它,以便按预期工作更多
答案 1 :(得分:2)
我不是SQL专家,所以我可能因为我的愚蠢而被投票,但我的猜测是,在第一种情况下,SQL在应用谓词之前获取整个视图的结果在WHERE子句中。因此,当您查询视图时,它会选择所有记录,将它们放入内存中,然后在完成后应用Date过滤器。
这似乎类似于在WHERE中应用过滤器之前获取连接中指定的整个数据集的方式(这里的教训是您应该在可能的情况下在ON子句中应用谓词)。
除非以某种方式区别对待观点。
答案 2 :(得分:2)
OVER()语法在SS2005中是全新的,显然没有很好地集成到优化器中。我建议你试试更传统的表达方式吗?如果你关心可优化性,可能不是表达。
http://www.sqlteam.com/article/sql-sever-2005-using-over-with-aggregate-functions
或者,更好的是,对剖析器更加熟悉 - 视图应该是可以修复的。
答案 3 :(得分:1)
从技术上讲,您不是在相同的SQL语句之间进行比较。您的视图表明它返回a.date, a.Col1, b.Col2,
加上您的DENSE_RANK()函数。在没有视图的查询中,您将返回所有列。
首先,您可能会认为返回所有列会更糟。但是如果不知道包括索引在内的表结构是什么样的话,很难确定哪个更好。
您是否比较了每个语句的查询计划?
答案 4 :(得分:-1)
作为一种解决方法,我建议使用函数而不是视图,以便传入数据参数。