Использование с vs объявляет временную таблицу: производительность/разность?
Я создал sql-функцию в SQLServer 2008, которая объявила временную таблицу и использует ее для вычисления скользящей средней по значениям внутри
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,[email protected] + 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?, но я не хочу, чтобы таблица сохранялась за пределами функции ( Я не уверен, делает ли это временную таблицу create или нет.)
Ответы
Ответ 1
Синтаксис @table
создает переменную таблицы (фактическую таблицу в tempdb
) и материализует результаты.
Синтаксис WITH
определяет Common Table Expression, который не является материализованным и является только встроенным представлением.
В большинстве случаев вам будет лучше использовать второй вариант. Вы говорите, что это внутри функции. Если это TVF, то большую часть времени вы хотите, чтобы они были встроенными, а не многозадачными, поэтому они могут быть расширены оптимизатором - это немедленно запретит использование табличных переменных.
Иногда (например, основной запрос стоит дорого, и вы хотите избежать его выполнения несколько раз), вы можете определить, что материализация промежуточных результатов повышает производительность в некоторых конкретных случаях. Существует в настоящее время нет пути для этого для CTE (без принуждения план по крайней мере)
В этом случае у вас (в общем) есть 3 варианта. A @tablevariable
, #localtemp
и таблицы ##globaltemp
. Однако только первая из них разрешена для использования внутри функции.
Для получения дополнительной информации о различиях между табличными переменными и таблицами #temp см. здесь.
Ответ 2
В дополнение к тому, что ответил Мартин
;with tempTable as
(
select * from aces.dbo.fEDVisitCounts('ALL', null,DATEADD(DD,-7,'01-09-2010'),
'04-09-2010',0,130,null,1, 0)
)
SELECT * FROM tempTable
также можно записать так:
SELECT * FROM
(
select * from aces.dbo.fEDVisitCounts('ALL', null,DATEADD(DD,-7,'01-09-2010'),
'04-09-2010',0,130,null,1, 0)
) AS tempTable --now you can join here with other tables
Ответ 3
Другим отличием является второй способ (with tableName as ...
) привести к временной таблице ReadOnly. Но в первую очередь (declare table
) вы можете изменить свои данные таблицы.