查询在条件IF中减慢

时间:2014-11-25 00:14:04

标签: sql sql-server tsql query-optimization

我注意到以下需要32秒才能在SQL Server(2008 R2)中运行

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秒但是查看执行计划却没有产生任何特别值得注意的东西。 Haven没有机会用Google搜索单词OR。

有人可以分享一下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:在比较了20页大小的查询计划之后 - 看起来加速主要是由于底层视图在连接之前进行了部分聚合,而不是进行连接然后聚合。

2 个答案:

答案 0 :(得分: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'

这是TOP的另一种方法,只有一种存在 - 也许是基于所提供的解释,为什么多个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的单个语句,性能可能会因您的情况而变慢。

答案 1 :(得分: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'