Когда я должен использовать переменную таблицы против временной таблицы в sql server?


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

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

но я не знаю, что "слишком много записей" есть. 100 000 записей? или 1000 000 записей? Как я могу узнать, находится ли переменная таблицы, которую я использую, в памяти или на диске? Есть ли какая-либо функция или инструмент в SQL Server 2005 для измерения масштаба переменной таблицы или предоставления мне знать, когда переменная таблицы помещается на диск из памяти?

6 240

6 ответов:

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

я написал довольно обширный ответ на сайте DBA смотреть на различия между двумя типами объектов. Это также касается вашего вопроса о диске и памяти (я не видел никакой существенной разницы в поведении между ними).

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

там, где у вас есть выбор, некоторые предложения приведены ниже (хотя самый надежный метод-просто проверить оба с вашей конкретной рабочей нагрузкой).

  1. если вы нужен индекс, который не может быть создан неявно через UNIQUE или PRIMARY KEY ограничение тогда вам нужно #temporary таблица, так как невозможно создать их на табличных переменных. (Примерами таких индексов являются неуникальные, отфильтрованные индексы или индексы с INCLUDEстолбцы D). Примечание: в SQL Server 2014 г позволит неуникальных индексов, чтобы быть объявлены как inline для табличных переменных.
  2. если вы будете повторно добавлять и удалять большое количество строк из таблицы, то используйте #temporary стол. Это поддерживает TRUNCATE (что более эффективно, чем DELETE для больших таблиц) и дополнительно последующие вставки после TRUNCATE может иметь лучшую производительность, чем те, которые следуют за DELETEкак показано здесь.
  3. если вы будете удалять или обновлять большое количество строк, то временная таблица может работать намного лучше, чем переменная таблицы - если она может использовать общий доступ к наборам строк (см. "эффекты совместного использования наборов строк" ниже образец.)
  4. если оптимальный план с использованием таблицы будет меняться в зависимости от данных, то используйте #temporary таблица. Это поддерживает создание статистики, которая позволяет динамически перекомпилировать план в соответствии с данными (хотя для кэшированных временных таблиц в хранимых процедурах перекомпиляции поведения нужно разбираться отдельно).
  5. если оптимальный план запроса с использованием таблицы вряд ли когда-либо изменится, вы можете рассмотреть таблицу переменная, чтобы пропустить накладные расходы на создание и перекомпиляцию статистики (возможно, потребуются подсказки для исправления нужного плана).
  6. если источник данных, вставленных в таблицу, является потенциально дорогим SELECT оператор затем рассмотрим, что использование табличной переменной заблокирует возможность этого с помощью параллельного плана.
  7. если вам нужны данные в таблице, чтобы пережить откат внешней пользовательской транзакции, используйте переменную таблицы. Возможный вариант использования для это может быть регистрация хода выполнения различных шагов в длинном пакете SQL.
  8. при использовании #temp таблица в пользовательской транзакции блокировки могут храниться дольше, чем для переменных таблицы (потенциально до конца транзакции против Конца оператора в зависимости от типа блокировки и уровня изоляции), а также это может предотвратить усечение tempdb журнал транзакций до завершения транзакции пользователя. Таким образом, это может способствовать использованию табличных переменных.
  9. сохраненные процедуры, как табличные переменные и временные таблицы могут быть кэшированы. Обслуживание метаданных для кэшированных табличных переменных меньше, чем для #temporary таблицы. Боб Уорд указывает в своем tempdb презентация что это может вызвать дополнительную конкуренцию в системных таблицах в условиях высокого параллелизма. Кроме того, при работе с небольшими объемами данных это может сделать измеримая разница в производительности.

эффекты совместного использования наборов строк

DECLARE @T TABLE(id INT PRIMARY KEY, Flag BIT);

CREATE TABLE #T (id INT PRIMARY KEY, Flag BIT);

INSERT INTO @T 
output inserted.* into #T
SELECT TOP 1000000 ROW_NUMBER() OVER (ORDER BY @@SPID), 0
FROM master..spt_values v1, master..spt_values v2

SET STATISTICS TIME ON

/*CPU time = 7016 ms,  elapsed time = 7860 ms.*/
UPDATE @T SET Flag=1;

/*CPU time = 6234 ms,  elapsed time = 7236 ms.*/
DELETE FROM @T

/* CPU time = 828 ms,  elapsed time = 1120 ms.*/
UPDATE #T SET Flag=1;

/*CPU time = 672 ms,  elapsed time = 980 ms.*/
DELETE FROM #T

DROP TABLE #T

использовать переменной в таблице Если для очень малого количества данных (тысячи байт)

использовать временная таблица для большого количества данных

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

в моем примере я просто хотел поместить около 20 строк в формат и изменить их как группу, перед использованием их для обновления / вставки постоянной таблицы. Таким образом, переменная таблицы идеально подходит.

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

Это не похоже на то, как CTE являются проблемой по причине аналогичного размера - если данные в CTE очень малы, я нахожу, что CTE работает так же хорошо, как и оптимизатор, но если это довольно большой, то это больно вам плохо.

мое понимание в основном основано на http://www.developerfusion.com/article/84397/table-variables-v-temporary-tables-in-sql-server/, который имеет гораздо больше деталей.

Microsoft говорит здесь

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

Я полностью согласен с Abacus (извините - не хватает очков для комментариев).

кроме того, имейте в виду, что это не обязательно сводится к сколько записи у вас есть, но в размере ваших записей.

например, вы рассмотрели разницу в производительности между 1000 записей с 50 столбцами каждый против 100 000 записей только с 5 столбцами каждый?

наконец, может быть, вы запрашиваете / храните больше данных, чем вам нужно? Это место хорошее чтение на стратегии оптимизации SQL. Ограничьте объем данных, которые вы вытягиваете, особенно если вы не используете все это (некоторые программисты SQL действительно ленятся и просто выбирают все, даже если они используют только крошечное подмножество). Не забывайте, что анализатор запросов SQL также может стать вашим лучшим другом.

переменной в таблице доступно только для текущего сеанса, например, если вам нужно EXEC другая хранимая процедура в рамках текущей вам придется передать таблицу как Table Valued Parameter и конечно это повлияет на производительность, с временные таблицы вы можете сделать это, только передав имя временной таблицы

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

  • открыть редактор запросов среды management studio
  • создать временную таблицу
  • открыть новое окно редактора запросов
  • выберите из этой таблицы "доступно"

для проверки таблицы переменных:

  • открыть редактор запросов management studio
  • создать переменную таблицу
  • открыть новое окно редактора запросов
  • выберите из этой таблицы "недоступно"

что-то еще у меня опытный: Если ваша схема не имеет GRANT привилегия для создания таблиц, а затем использовать переменные таблицы. Кроме того, временные таблицы, расположенные в базе данных tempdb, и переменные таблицы могут быть расположены как в памяти, так и на диске базы данных tempdb. Смотрите здесь: https://www.linkedin.com/pulse/highlighted-differences-between-sql-server-temporary-tables-andrew

запись данных в таблицах объявлен declare @tb и после объединения с другими таблицами, я понял, что время отклика по сравнению с временными таблицами tempdb .. # tb значительно выше.

когда я присоединюсь к ним с @tb время гораздо больше времени, чтобы вернуть результат, в отличие от #tm возвращение почти мгновенно.

Я сделал тесты с 10 000 строк присоединиться и присоединиться к 5 другим таблицам