SQL查询UNION性能

时间:2012-03-27 09:15:08

标签: sql-server performance database-performance query-performance

更新

我认为现在提出这个问题还为时过早。经过几次测试后,我发现性能没有提高。我将在这里执行更多测试并发布更新。直到那时,不要费心回答这个问题。

我有这样的查询...

SELECT DISTINCT TOP 11 [Field_A] 
FROM   [#TempTable] 
WHERE  [Field_A] NOT IN (SELECT bo.[Id] 
                         FROM   [BusinessObject_Table] bo 
                         UNION 
                         SELECT boTemp.[Id] 
                         FROM   [#BusinessObject_Table] boTemp) 

这个查询需要永远运行一个相当大的数据集。我还在Temp表的Id列上添加了CLUSTERED索引,这样可以获得一些性能提升,但仍然无法完成。

我用这个替换了这个查询...

SELECT DISTINCT TOP 11 [Field_A] 
FROM   [#TempTable] 
WHERE  [Field_A] NOT IN (SELECT bo.[Id] 
                         FROM   [BusinessObject_Table] bo) 
       AND [Field_A] NOT IN (SELECT boTemp.[Id] 
                             FROM   [#BusinessObject_Table] boTemp) 

这在几秒钟内完成。有人能解释一下这里发生了什么吗?

更新: 我认为两个查询都是一样的。这就是我需要的。

BusinessObject_Table has following Ids: 1, 2, 3

#BusinessObject_Table has: 3, 4, 5

TempTable has rows whose Field_A values are: 1, 2, 3, 4, 6

查询结果应为:6(注意上面查询中的更改)

我将尝试获取查询计划并在此处发布。

2 个答案:

答案 0 :(得分:3)

在没有查询计划时猜测......

子查询中的UNION强制执行DISTINCT。使用单独的IN子句,可以避免这种情况。但是,查询之间的逻辑是不同的(编辑:正如Martin Smith所说)

如果这是你想要的逻辑,那么使用UNION ALL和单个IN应该会更好

WHERE  [Field_A] NOT IN (SELECT bo.[Id] 
                     FROM   [BusinessObject_Table] bo 
                     UNION ALL
                     SELECT boTemp.[Id] 
                     FROM   [#BusinessObject_Table] boTemp)

答案 1 :(得分:2)

我认为你应该这样做:

SELECT DISTINCT TOP 11 [Field_A] 
FROM   [#TempTable] 
WHERE NOT EXISTS(
  SELECT 1 FROM BusinessObject_Table bo WHERE #TempTable.FieldA = bo.Id
) AND NOT EXISTS(
  SELECT 1 FROM #BusinessObject_Table bo WHERE #TempTable.FieldA = bo.Id
) 

这样SQL Server可以使用它的优化器可能比你的UNIONed查询好一点。优化程序可能会根据您的索引策略和表大小选择以不同的顺序运行查询。最有可能的是,这将是最快的方式。虽然没有表格结构和索引以及执行计划,但很难确定。