2013-07-19 37 views
2

对SQL Server的这种行为感到好奇。IN语句挂起SQL Server中的SELECT子查询

这个查询产生的结果非常快,就像我期望:

SELECT * 
FROM dbo.v_View1 View1 FULL OUTER JOIN 
    dbo.v_View2 View2 ON View1.Portfolio = View2.Portfolio AND 
    View1.AsOfDate = View2.AsOfDate 
where (View1.AsOfDate IN (NULL, '20130717')) 

不过,我不希望有一个静态日期在那里,所以我用一个子查询代替它。不幸的是,我已经等待这个查询执行的时间最长为5分钟之前,我取消了,所以我不知道它是否确实会得到我的数据我想:

SELECT * 
FROM dbo.v_View1 View1 FULL OUTER JOIN 
    dbo.v_View2 View2 ON View1.Portfolio = View2.Portfolio AND 
    View1.AsOfDate = View2.AsOfDate 
where (View1.AsOfDate IN (NULL, (SELECT MAX(AsOfDate) FROM dbo.v_View1))) 

我使出声明一个变量,用上面的子查询设置它,然后在IN语句中使用它,该语句按预期工作,并且运行速度与原始查询快一样。

我知道我做错了什么或错过了什么(可能两者) - 它是什么?我希望在IN语句中有子查询,或者至少能够将这个作为没有变量的视图运行。谢谢!

+2

看看执行计划。 –

回答

4

我怀疑查询优化器正在做一些非常奇怪的事情,因为天真的实现涉及两个扫描v_View1也许优化器未能认识到子查询SELECT MAX(AsOfDate) ...将是每行相同。我怀疑它可能没有意识到子查询与每一行都没有关联,因此对于结果集的每一行都运行它。鉴于完整的外连接,大量数据意味着大量不必要的表扫描。

简单的解决办法是:

DECLARE @MaxAsOfDate datetime; 
SET @MaxAsOfDate = (SELECT MAX(AsOfDate) FROM dbo.v_View1) 

SELECT * 
FROM dbo.v_View1 View1 FULL OUTER JOIN 
    dbo.v_View2 View2 ON View1.Portfolio = View2.Portfolio AND 
    View1.AsOfDate = View2.AsOfDate 
where (View1.AsOfDate IN (NULL, @MaxAsOfDate)) 

这将迫使子查询执行一次,结果存储在变量,然后利用它来进行下面的查询。

+0

是的,我一直在存储过程中而不是在视图中这样做(这看起来更正确,因为视图设计器没有变量的视觉支持),但希望我只是遗漏了什么。哦,好的 - 谢谢! –

2

我相信它会重新计算每个记录的MAX(AsOfDate)。一个简单的解决方案是使用WITH子句(也称为公用表表达式),它只能在开始时计算。

0

一个简单的方法来改写这个,为了避免这个问题,就是:

where View1.AsOfDate is null or View1.AsOfDate = (SELECT MAX(AsOfDate) FROM dbo.v_View1) 

编辑:

你的问题是该查询运行多次。你的问题是这个视图是非常不优化的。你可以通过重新编译视图来解决这个问题。在SSMS中将其作为ALTER陈述进行编写并执行。自创建视图以来,基础表可能已更改。

我想你也可以通过告诉SQL Server不要使用嵌套循环连接(这是你的性能问题的原因)来解决这个问题。您可以通过将option (hash join, merge join)添加到SQL语句的末尾来完成此操作。

+0

谢谢,但这对我来说是同样的问题 - 目前已经运行了5分钟。 –

1

我会建议使用最上面的一个,并改变它,所以它不具有对中陈述NULL这么写像这样

SELECT * 
FROM dbo.v_View1 View1 FULL OUTER JOIN 
    dbo.v_View2 View2 ON View1.Portfolio = View2.Portfolio AND 
    View1.AsOfDate = View2.AsOfDate 
where View1.AsOfDate IN ('20130717') AND View1.AsOfDate IS NULL 

也是完全外连接需要的?或者可以使用INNER JOIN?

此外,如果你看看执行计划和岗位,我将能够张贴关于如何最好地优化这个查询,你还会看到什么点的详细信息,查询耗时最长

Picture of execution plan and how to show it

+0

谢谢 - 这不能解决我想在'WHERE'语句中使用动态AsOfDate的问题。我会看看执行计划,看看有没有什么可疑的东西,谢谢你的提示。 –