我对使用CTE来缩小结果的非常大的表的查询效果不佳。 CTE最多可产生三行,它是通过从源表中获取最大合计值,然后使用CROSS APPLY和标量函数来产生所需的列而产生的。
有趣的是,如果我将CTE中的数据加载到一个表变量中并将该表变量连接到源表中,那么查询的性能将大大提高。
查询计划非常不同:
解决此问题的方法是什么,以便我可以只使用CTE-可能是某种查询或联接提示?
-- table variable for alt version of query
-- DECLARE @PeriodsTbl TABLE (PeriodCode varchar(10), PeriodDate date, PeriodDateKey int);
WITH PeriodsSource AS (
SELECT forPeriods.*, forPeriodDateKeys.*
FROM (SELECT dbo.DateKeyToDate(MAX(EndDateKey)) MaxDate FROM BigTable) forMaxDate
CROSS APPLY (
SELECT x.*, dbo.DateToDatekey(x.PeriodDate) PeriodDateKey
FROM ( VALUES
( 'cur', CAST(MaxDate AS DATE) )
, ( 'pw', CAST(DATEADD(day, -7, MaxDate) AS DATE) )
, ( 'py', CAST(DATEADD(day, -364, MaxDate) AS DATE) )
) x ( PeriodCode, PeriodDate )
) forPeriods
)
--INSERT INTO @PeriodsTbl
--SELECT PeriodCode, PeriodDate, PeriodDateKey
--FROM PeriodsSource ps;
SELECT *
FROM PeriodsSource ps -- Use @PeriodsTbl For Table Version
INNER JOIN BigTable bt ON bt.StartDateKey <= ps.PeriodDateKey
AND bt.EndDateKey >= ps.PeriodDateKey
答案 0 :(得分:1)
我的猜测是性能问题是由于标量函数的自由使用。从性能角度来看,它们通常很糟糕。将这些转换为内联表值函数将是我的第一步。但是请确保它们不是多语句表值函数,否则您实际上可能会倒退以提高性能。或者,如果函数非常简单,则可以内联逻辑,这会更好。
编辑
在联接中使用标量函数导致计划从更有效的联接变为一个联接,而无需谓词和之后的过滤。 PeriodDateKey
是在CTE中由函数DateToDatekey
生成的,这就是BigTable所要连接的内容。将其更改为功能上等效的表达式会导致计划发生更改,并产生了很大的改进。
尝试将函数调用移至CROSS APPLY之外并没有带来任何改善,并且尽管删除了对标量函数的所有引用都产生了性能提升,但它不如对PeriodDateKey
进行一次更改所实现的增益重要。 / p>