当从带有外部参数化“ where”子句的视图中调用时,窗口函数会导致糟糕的执行计划


10

很久以前,我遇到了这个问题,我找到了适合自己的解决方法,却忘了它。

但是现在在SO上存在这个问题,所以我愿意提出这个问题。

有一个视图以非常简单的方式(订单+订单行)连接了几个表。

当查询不带where子句的视图时,该视图将返回几百万行。
但是,没有人会这样称呼它。通常的查询是

select * from that_nasty_view where order_number = 123456;

这将返回5m中的10条记录。

重要的是:该视图包含一个窗口函数,该窗口函数rank()完全由始终查询该视图的字段划分:

rank() over (partition by order_number order by detail_line_number)

现在,如果使用查询字符串中的文字参数查询此视图(完全如上所示),它将立即返回行。执行计划很好:

  • 使用on的索引在两个表上进行索引查找order_number(返回10行)。
  • 在返回的微小结果上计算窗口。
  • 选择。

但是,当以参数化方式调用视图时,情况会变得很糟:

  • Index scan在所有表上忽略索引。返回5m行。
  • 巨大的加入。
  • 计算所有partitions上的窗口(约50万个窗口)。
  • Filter 从5m中取出10行。
  • 选择

在涉及参数的所有情况下都会发生这种情况。可以是SSMS:

declare @order_number int = 123456;
select * from that_nasty_view where order_number = @order_number;

它可以是ODBC客户端,例如Excel:

select * from that_nasty_view where order_number = ?

也可以是使用参数而不使用sql串联的任何其他客户端。

如果将窗口函数从视图中删除,则无论是否使用参数查询,它都能完美快速地运行。

我的解决方法是删除有问题的功能,然后在稍后阶段重新应用它。

但是,有什么用呢?这真的是SQL Server 2008如何处理窗口功能的错误吗?


order_number是主键?列和参数的数据类型是否匹配?
— gbn 2012年

order_number不是主键。它是int not null用两个表中就可以了非聚集索引。
— GSerg

5
SQL Server 2005 在这方面的谓词推送存在问题。我以为他们已经修复了。顺便说一句,您的TSQL示例使用变量而不是参数。添加OPTION (RECOMPILE)帮助吗?
— 马丁·史密斯

1
@GSerg-那么在过滤器的坏计划上,它最后有大约500万行进入过滤器,并且估计有10行与实际匹配?如果是这样,那么谓词推送问题仍然没有完全解决。
— 马丁·史密斯

Answers:


5

这似乎是一个长期存在的问题,它以一种或另一种形式重新铺装,并在SQL Server 2012中仍然存在。

一些讨论它的帖子是

直到(包括2012年)的所有当前版本的SQL Server都不能将分区组上的筛选器推过参数化谓词的序列项目的序列项目,除非option(recompile)已使用(如果使用2008+)。

recompile提示的替代方法是重写查询,以使用由@ a1ex07建议的参数化嵌入式TVF。


SQL Server 2014中也有这种情况
— Guillaume86'6

3

我尝试用表值udf替换视图。这样,它将首先过滤记录,然后再应用窗口功能。此函数可以接受表参数,因此您可以将多个参数传递order_number给它


是另一种解决方法,是的。但我不能这样做,因为并非所有客户端都可以使用表值函数。
— GSerg

为什么?我不确定100%,但是我想您所需要的只是将查询稍微更改为类似内容SELECT * FROM my_funct(12345)
— a1ex07 '02

要求之一是该查询可由最终用户使用Excel(即通过MS Query)使用,并且MS Query不允许您这样做,至少在2003
— 之前的

it will filter records first, and then apply window function是不正确的。没有确定的执行顺序
— Remus Rusanu 2013年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.