如何提高具有UNION和子选择的sql查询的性能?

时间:2011-11-25 13:01:24

标签: sql sql-server tsql

我对mssql 2008有一个看法.T-SQL代码如下所示,

SELECT     *
FROM        View1
WHERE     Category = 1
UNION ALL
SELECT     *
FROM         View1 AS Level#1
WHERE    Category = 2 AND NOT EXISTS
                          (SELECT     *
                            FROM          View1
                            WHERE      Level#1.Code = Code AND CategoryCode = 1)

P.S。代码; 代码的dataype是nvarchar - View1是相同的视图

当我从大约3500条记录中执行此代码时,结果将超过5分钟。

如何修改此代码以快速执行? 现在谢谢你的建议。

4 个答案:

答案 0 :(得分:1)

您的问题(包含给定信息)是一个视图和SELECT *

  • 视图只是一个扩展到原始表的宏。因此,如果视图有4个表,那么您的UNION现在具有相同的4个表,每个表使用次数

  • SELECT *也意味着索引将无法有效使用(如果有的话)。您将在执行计划中获得扫描或密钥查找,因为您无法使用覆盖索引等

如果您的视图位于单个表上,那么它可能会被抢救,但您也可以使用临时表来执行此操作。

答案 1 :(得分:0)

不知道你的表/索引定义是什么,所以我可能错了,但这个代码乍一看似乎没必要:

AND NOT EXISTS
                          (SELECT     *
                            FROM          View1
                            WHERE      Level#1.Code = Code AND CategoryCode = 1)

因为WHERE Category = 2

的第二个句子中已经有UNION ALL

答案 2 :(得分:0)

如果您使用的是SQL Server 2005或更高版本,可以尝试以下方法:

WITH ranked AS (
  SELECT
    *,
    rnk = RANK() OVER (PARTITION BY Code ORDER BY Category)
  FROM View1
  WHERE Category IN (1, 2)
)
SELECT
  *  /* this will include the 'rnk' column too;
        in any event, masked output is a very
        discouraged thing to do so you should
        probably specify the columns explicitly */
FROM ranked
WHERE rnk = 1

如果每个Code永远不会有多个Category,请将RANK()替换为ROW_NUMBER(),这应该更有效。

有用的阅读:

答案 3 :(得分:0)

不是100%确定我理解您的查询,但请尝试这一点,看看您是否得到了相同的(预期)结果:

SELECT     *
FROM        View1
WHERE     Category = 1
UNION ALL
SELECT     *
FROM         View1 AS Level#1
LEFT JOIN View1 as XX ON Level#1.code=XX.Code and XX.CategoryCode =1 
WHERE    Level#1.Category = 2 AND xx.code is NULL