一尘不染

与vs一起使用时会声明一个临时表:性能/差异?

sql

我在 SQLServer 2008 中创建了一个sql函数,该函数声明了一个临时表,并使用它来计算内部值的移动平均值

declare @tempTable table 
    (
        GeogType nvarchar(5),
        GeogValue nvarchar(7),
        dtAdmission date,
        timeInterval int,
        fromTime nvarchar(5),
        toTime nvarchar(5),
        EDSyndromeID tinyint,
        nVisits int
    )
insert @tempTable select * from aces.dbo.fEDVisitCounts(@geogType, @hospID,DATEADD(DD,-@windowDays + 1,@fromDate),
                @toDate,@minAge,@maxAge,@gender,@nIntervalsPerDay, @nSyndromeID)


    INSERT @table (dtAdmission,EDSyndromeID, MovingAvg) 
    SELECT list.dtadmission
        , @nSyndromeID
        , AVG(data.nVisits) as MovingAvg
    from @tempTable as list 
        inner join @tempTable as data  
    ON list.dtAdmission between data.dtAdmission and DATEADD(DD,@windowDays - 1,data.dtAdmission) 
    where list.dtAdmission >= @fromDate
    GROUP BY list.dtAdmission

但我还发现,您可以像这样声明tempTable:

with tempTable as 
(
    select * from aces.dbo.fEDVisitCounts('ALL', null,DATEADD(DD,-7,'01-09-2010'),
        '04-09-2010',0,130,null,1, 0)
)

问题:这两种方法是否有重大区别?
一个比另一个或更通用/标准快吗?
我认为声明速度更快,因为您定义了要查找的列。如果我省略移动平均值计算中未使用的列,它还会更快吗?(不确定这一行)因为无论如何都要获得所有行,尽管选择较少的列在直觉上就意味着它会更快/更少地执行)

我还create temporary table @table从这里找到了一个如何在MySQL中声明内部表?但我不希望该表保留在函数之外(我不确定创建临时表是否执行此操作。)


阅读 135

收藏
2021-03-17

共1个答案

一尘不染

@table语法创建一个表变量(中的实际表tempdb),并将结果具体化为该变量。

WITH语法定义了一个公共表表达式,该未实现,只是一个内联视图。

在大多数情况下,使用第二个选项会更好。您提到这在函数内部。如果这是TVF,那么大多数时候您希望它们是内联而不是multi语句,以便可以通过优化程序将其扩展-
这将立即禁止使用表变量。

但是有时(例如,基础查询很昂贵,并且您希望避免多次执行该查询),您可能会确定在某些特定情况下,实现中间结果可以提高性能。有目前还没有办法迫使本作的热膨胀系数(不强制至少一个计划指南

在这种情况下,您(通常)有3个选择。A
@tablevariable#localtemp一张桌子和一张##globaltemp桌子。但是,仅其中的第一个允许在函数内部使用。

有关表变量和#temp表之间差异的更多信息,请参见此处

2021-03-17