代码之家  ›  专栏  ›  技术社区  ›  Daniel Gimenez

使用CTE和标量函数查询的错误查询计划

  •  0
  • Daniel Gimenez  · 技术社区  · 8 年前

    有趣的是,如果我将CTE中的数据加载到表变量中,并将表变量连接到源表中,那么查询的性能将显著提高。

    查询计划非常不同:

    • CTE版本有一个嵌套循环连接,它指定“Warning:No join Predicate”,然后它有一个过滤器,该过滤器使用我认为应该是连接谓词的内容。
    • 表变量版本有两个嵌套的循环联接,没有筛选器操作。

    -- 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
    
    1 回复  |  直到 8 年前
        1
  •  1
  •   Daniel Gimenez    8 年前

    我猜性能问题是因为标量函数的自由使用。从表演的角度来看,它们通常都很糟糕。将它们转换为内联表值函数将是我的第一步。不过,请确保它们不是多语句表值函数,否则您可能实际上会为了性能而倒退。或者,如果函数相当简单,您可以直接内联逻辑,这样会更好。

    编辑

    连接中的标量函数 导致计划从一个更有效的连接更改为一个不带谓词和筛选的连接。 PeriodDateKey 在CTE中从函数 DateToDatekey 这就是加入BigTable的原因。将它改为功能等价的表达式,导致了计划的改变,并产生了很大的改进。

    周期日期键