我的任务是增强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
答案 0 :(得分:2)
我改进此查询的第一步是:
降低代码复杂性:为什么使用两个CTE?从示例代码中可以看出,这可以重写为单个查询,将表1连接到2,然后连接到2到3,ROW_NUMBER()直接在SELECT子句中。这可能不会直接影响性能,但分析简单查询比复杂查询要容易得多。
重新考虑ROW_NUMBER()的预期行为:您正在按同一列进行分区和排序。这意味着对于column1中的每个不同值,SQL Server将尝试根据column1中的值对行进行排序;这个值在该分区中都是相同的,因此排序基本上是"随机的"任何专门用于此的处理时间都被浪费了。 (主要取决于其他因素,例如这些表上的任何聚簇索引。)
检索此查询的执行计划并检查它以获取更多想法。执行计划可能包括可以应用的索引提示 - 您应该考虑这些提示,但不要将SQL Server的单词作为福音。
如果我能看到执行计划,对这些表的结构(包括关系的索引和基数)有更深入的了解,并且知道有多大"非常大"我可能会有进一步的建议。意味着你:)