2014-11-25 40 views
1

我注意到下面的时间是32秒在SQL Server(2008 R2)查询减慢条件下IF

IF ((SELECT COUNT(*) FROM view1) != 0) 
    OR ((SELECT COUNT(*) FROM view2) != 0) 
    OR ((SELECT COUNT(*) FROM view3) != 0) 
    OR ((SELECT COUNT(*) FROM view4) != 0) 
    OR ((SELECT COUNT(*) FROM view5) != 0) 
    OR ((SELECT COUNT(*) FROM view6) != 0) 
     PRINT 'HI' 

运行然而,只有以下了4秒

SELECT 
    (SELECT COUNT(*) FROM view1) 
    , (SELECT COUNT(*) FROM view2) 
    , (SELECT COUNT(*) FROM view3) 
    , (SELECT COUNT(*) FROM view4) 
    , (SELECT COUNT(*) FROM view5) 
    , (SELECT COUNT(*) FROM viwe6) 

我有设法通过执行SELECT COUNT(1)... + SELECT ...!= 0来优化条件,这样它需要4秒,但是查看执行计划还没有产生任何特别显着的结果。没有太多的机会用google搜索词或者。

有人可以分享一下SQL Server优化器可能在背后做什么吗?

编辑:如果EXISTS尝试了38秒。

IF EXISTS ((SELECT 1 FROM view1) 
    UNION (SELECT 1 FROM view2) 
    UNION (SELECT 1 FROM view3) 
    UNION (SELECT 1 FROM view4) 
    UNION (SELECT 1 FROM view5) 
    UNION (SELECT 1 FROM view6)) 
     PRINT 'HI' 

EDIT2:目前的第5种方法。

IF (SELECT COUNT(1) FROM view1) 
    + (SELECT COUNT(1) FROM view2) 
    + (SELECT COUNT(1) FROM view3) 
    + (SELECT COUNT(1) FROM view4) 
    + (SELECT COUNT(1) FROM view5) 
    + (SELECT COUNT(1) FROM viwe6) != 0 
     PRINT 'HI' 

EDIT3:比较20page大小的查询计划之后 - 它出现的加速主要是由于基本观点都做了局部聚集的加入,而不是做连接,然后汇总之前。

+0

你做EXISTS获得更好的性能(SELECT 1 FROM厂景),因为这会停止寻找它发现一排后,而不是统计所有行。 – Brandon 2014-11-25 01:31:33

+0

我确实尝试了EXISTS。但它也花了大约38秒。我会把我在编辑中尝试的东西放进去。 – 2014-11-25 01:43:45

+0

一个快速的想法把计数结果放到变量中,然后使用IF条件 – 2014-11-25 06:55:51

回答

0

下面的代码需要多长时间才能运行?如果将查询转换为EXISTS,则需要避免使用UNION,因为在您的示例中,每个视图的每行都会强制SQL为UNION,然后查看是否存在元素。下面的答案将有机会尽快停止。

IF EXISTS(SELECT 1 FROM view1) 
    OR EXISTS(SELECT 1 FROM view2) 
    OR EXISTS(SELECT 1 FROM view3) 
    OR EXISTS(SELECT 1 FROM view4) 
    OR EXISTS(SELECT 1 FROM view5) 
    OR EXISTS(SELECT 1 FROM view6) 
    PRINT 'HI' 

这里是用一个顶部的另一种方法存在 - 也许是基于对为何多EXISTS被执行,所以慢慢地你应该更好的提供解释。

IF EXISTS (
    SELECT TOP (1) 1 FROM view1 
    UNION ALL SELECT TOP (1) 1 FROM view2 
    UNION ALL SELECT TOP (1) 1 FROM view3 
    UNION ALL SELECT TOP (1) 1 FROM view4 
    UNION ALL SELECT TOP (1) 1 FROM view5 
    UNION ALL SELECT TOP (1) 1 FROM view6 
    ) 
    PRINT 'Hi' 

至于在引擎盖下你的问题,下面的网址具有良好的书面记录: http://sqlserverplanet.com/tsql/comparing-exists-vs-left-join-where-not-null

基本上,它描述了使用EXISTS时,单语句与不创建一个工作表,以便多个EXISTS,性能可能会变慢,就像你的情况一样。

+0

没多少运气,花了29秒。 我推测问题不是'退出'尽快 - 而是由于if语句导致执行计划不佳的底层SQL优化引擎。我仍然在质疑为什么以及它可能在底层做什么。 – 2014-11-25 06:47:21

+0

你可以运行备用查询吗?我添加了一些信息和博客文章的链接,说明为什么像这样的多个EXISTS在某些情况下可能会变慢。 – 2014-11-25 13:02:21

+0

有趣的是执行计划是用于上述两种查询的相同,但假想的单个EXISTS应该更加优化 – 2014-11-25 13:03:12

0

使用TOP 1语句:

例如:

DECLARE @CONTROL INT; 
WITH CTE AS (
SELECT TOP 1 col FROM view1 
UNION ALL 
SELECT TOP 1 col FROM view2 
UNION ALL 
SELECT TOP 1 col FROM view3 
UNION ALL 
SELECT TOP 1 col FROM view4 
UNION ALL 
SELECT TOP 1 col FROM view5 
UNION ALL 
SELECT TOP 1 col FROM view6) 

SELECT @CONTROL = COUNT(col) FROM CTE 

IF @CONTROL != 0 
PRINT 'HI'