在视图中使用row_number(partition by ...)无休止地运行vs作为查询运行

时间:2015-09-15 20:54:51

标签: sql sql-server

我的任务是增强SQL视图以提高性能,该代码的伪代码如下所示。它有row_number over(partition by ... order by ...),这似乎导致这个视图无限期地运行,直到我终止查询。 即当我运行select * from view_name where Date = '2015-01-31'时,它会永远运行。但是如果我将整个视图作为查询运行(例如,在顶部删除alter view语句并在代码末尾传递where子句),它运行正常。

我正在使用SQL 2005.可能SQL 2005引擎为视图和普通查询生成不同的执行计划,因为我提到视图中的整个代码,当作为查询执行时,运行正常。如何让视图本身运行得更快,以便返回结果?我的视图查询的其中一个表(此psuedo代码中的table1)非常大,并按日期进行分区,其中每个月的数据是一个分区。

伪码:

CREATE VIEW Sample
AS
WITH Dataset1
AS (
    SELECT table1.DATE
        ,column1
        ,column2
        ,column3
        ,column4
    FROM table1
    INNER JOIN table2 ON table1.DATE = table2.DATE
    )
    ,Dataset2
AS (
    SELECT Dataset1.DATE
        ,column1
        ,column2
        ,column3
        ,column4
    FROM table3
    INNER JOIN Dataset1 ON table3.column1 = Dataset1.column1
    )
SELECT ROW_NUMBER() OVER (
        PARTITION BY column1 ORDER BY column1 ASC
        ) AS RowNumber
    ,*
FROM Dataset2
GO

1 个答案:

答案 0 :(得分:2)

我改进此查询的第一步是:

  1. 降低代码复杂性:为什么使用两个CTE?从示例代码中可以看出,这可以重写为单个查询,将表1连接到2,然后连接到2到3,ROW_NUMBER()直接在SELECT子句中。这可能不会直接影响性能,但分析简单查询比复杂查询要容易得多。

  2. 重新考虑ROW_NUMBER()的预期行为:您正在按同一列进行分区和排序。这意味着对于column1中的每个不同值,SQL Server将尝试根据column1中的值对行进行排序;这个值在该分区中都是相同的,因此排序基本上是"随机的"任何专门用于此的处理时间都被浪费了。 (主要取决于其他因素,例如这些表上的任何聚簇索引。)

  3. 检索此查询的执行计划并检查它以获取更多想法。执行计划可能包括可以应用的索引提示 - 您应该考虑这些提示,但不要将SQL Server的单词作为福音。

  4. 如果我能看到执行计划,对这些表的结构(包括关系的索引和基数)有更深入的了解,并且知道有多大"非常大"我可能会有进一步的建议。意味着你:)