看看这个 fiddle :http://sqlfiddle.com/#!6/18324/2
展开第一个执行计划,用于针对 View B
的查询.
请注意,第一个查询使用索引查找执行,而第二个查询 - 使用索引扫描。在我的实际设置中,有数千行,这会产生相当可观的性能损失。
卧槽???
查询是等价的,不是吗?为什么文字会产生搜索和变量扫描?
但更重要的是:我该如何解决这个问题 ?
This post最接近问题,从那里开始工作的解决方案是使用 option(recompile)
(谢谢你,马丁史密斯)。但是,这对我不起作用,因为我的查询是由我的 ORM 库(即 Entity Framework )生成的,我无法手动修改它们。
相反,我正在寻找的是一种重新制定 B
的方法。查看,以免出现问题。
在摆弄这个问题的同时,我注意到丢失谓词的总是执行计划中的“段”块。为了验证这一点,我用 min
根据子查询重新构造了查询。功能(见 View D
)。瞧! - 针对 D
的两个查询 View 产生相同的计划。
然而,坏消息是我不能使用这个 min
- 强力技巧,因为在我的真实设置中,列 Y
实际上是 几列 ,以便我可以通过他们订购,但我不能接受 min()
其中。
所以第二个问题是:谁能想出一个类似于最小驱动子查询的技巧,但适用于多列?
注 1 : 这个肯定和引爆点没有关系,因为表里只有2条记录。
注释 2 :它也与 View 的存在无关。查看带有 View 的示例 C
:在这种情况下,服务器很乐意使用seek。
最佳答案
可能这个会起作用
select a.X, a.Y from A a
cross apply
(select top 1 * from A t where t.X = a.X order by t.Y asc) as idx
SQLFiddle http://sqlfiddle.com/#!6/a3362/2
关于当使用窗口函数并且谓词包含变量时,SQL Server 使用扫描而不是搜索,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12976486/