INSERT разница в производительности между временными таблицами и табличными переменными

12

У меня есть следующая проблема в SQL Server 2005: попытка вставить некоторые строки в табличную переменную занимает много времени по сравнению с той же вставкой с использованием временной таблицы.

Это код для вставки в табличную переменную

DECLARE @Data TABLE(...)
INSERT INTO @DATA( ... )
SELECT ..
FROM ...

Это код для вставки во временную таблицу

CREATE #Data TABLE(...)
INSERT INTO #DATA( ... )
SELECT ..
FROM ...
DROP TABLE #Data

Временная таблица не имеет ключей или индексов, часть выбора одинакова для двух запросов, а число результатов, возвращаемых выбором, составляет ~ 10000 строк. Время, необходимое для выполнения одного выбора, составляет ~ 10 секунд.

Версия временной таблицы занимает до 10 секунд, мне пришлось остановить версию переменной таблицы через 5 минут.

Я должен использовать переменную таблицы, потому что запрос является частью функции табличного значения, которая не разрешает доступ к временной таблице.

План выполнения для версии табличной переменной План выполнения

План выполнения для версии временной таблицы План выполнения

munissor
источник

Ответы:

8

Очевидное различие между этими двумя планами состоит в том, что быстрый параллельный, а медленный последовательный.

Это одно из ограничений планов, которые вставляются в переменные таблицы. Как уже упоминалось в комментариях (и кажется, что это дало желаемый эффект), вы можете попробовать сделать

INSERT INTO @DATA ( ... ) 
EXEC('SELECT .. FROM ...')

чтобы увидеть, если это обходит ограничение.

Мартин Смит
источник
Это было отличное предложение, хотя я подумал, что вы не можете использовать EXECкакую-либо функцию ... думаю, я ошибся
Ламак
1
@ Ламак - Дох! Вы не можете, так что это не будет работать для ОП. Invalid use of a side-effecting operator 'INSERT EXEC' within a function., Работа вокруг может работать , хотя. OPENQUERY
Мартин Смит
Ах, приятно знать, спасибо за разъяснения
Ламак
2
Как правило, вы не хотите использовать табличные переменные, если ожидаете получить большой набор данных. В этом случае временные таблицы обычно быстрее.
HLGEM
1
@munissor, тогда не используйте табличную функцию. Если вы хотите получить лучший совет, напишите, что именно вы делаете.
HLGEM
-1

Табличные переменные иногда медленнее, потому что нет статистики по табличным переменным, и поэтому оптимизатор всегда предполагает только одну запись.

Однако я не могу гарантировать, что это именно тот случай, вам нужно взглянуть на информацию «оценочных строк» ​​в плане запроса для табличной переменной.

Йоэль Хэлб
источник
Как это повлияет на вставку в табличную переменную?
Мартин Смит
Похоже, именно это и происходит, поскольку вы можете видеть, что существует не только разница между параллельным и последовательным, но также и между соединениями хеш-функций и вложенных циклов, по-видимому, оптимизатор предполагает, что, поскольку табличная переменная содержит в себе одну запись, тогда результат запроса также будет одна запись, еще раз, единственный способ доказать, что он будет видеть фактическую статистику для каждой части запроса, но факт в том, что все запросы, включающие переменные таблицы, заканчиваются соединениями цикла и последовательной обработкой, так что я думаю, что это справедливо подозревать здесь
Йоэл Хэлб