Я изучаю больше деталей в табличной переменной. В нем говорится, что временные таблицы всегда находятся на диске, а переменные таблицы находятся в памяти, то есть производительность табличной переменной лучше, чем у временной таблицы, поскольку переменная таблицы использует меньше операций ввода-вывода, чем временная таблица.
Но иногда, если в табличной переменной слишком много записей, которые не могут содержаться в памяти, табличная переменная будет помещена на диск как временная таблица.
Но я не знаю, что такое «слишком много записей». 100 000 записей? или 1000 000 записей? Как я могу узнать, находится ли используемая в таблице переменная в памяти или на диске? Есть ли какая-либо функция или инструмент в SQL Server 2005, чтобы измерить масштаб табличной переменной или сообщить мне, когда табличная переменная помещается на диск из памяти?
tempDB
- это «в памяти» - это миф. Также: переменные таблицы всегда будут считаться оптимизатором запросов для хранения ровно одной строки - если у вас их намного больше, это может привести к серьезным неудачным планам выполнения.tempdb
(но может быть и полностью в памяти)Ответы:
Ваш вопрос показывает, что вы уступили некоторым распространенным заблуждениям, связанным с табличными переменными и временными таблицами.
Я написал довольно обширный ответ на сайте DBA, в котором рассматриваются различия между двумя типами объектов. Это также отвечает на ваш вопрос о дисках и памяти (я не видел существенной разницы в поведении между ними).
Что касается вопроса в заголовке о том, когда использовать переменную таблицы против локальной временной таблицы, у вас не всегда есть выбор. Например, в функциях можно использовать только переменную таблицы, и если вам нужно записать данные в таблицу в дочерней области, то
#temp
подойдет только таблица (табличные параметры разрешают доступ только для чтения). ).Там, где у вас есть выбор, ниже приведены некоторые предложения (хотя самый надежный метод - просто протестировать оба варианта с вашей конкретной рабочей нагрузкой).
Если вам нужен индекс, который нельзя создать для табличной переменной, тогда вам, конечно, понадобится
#temporary
таблица. Детали этого зависят от версии, однако. Для SQL Server 2012 и ниже единственными индексами, которые могли быть созданы для табличных переменных, были те, которые неявно создавались с помощью ограниченияUNIQUE
илиPRIMARY KEY
. SQL Server 2014 ввел синтаксис встроенного индекса для подмножества параметров, доступных вCREATE INDEX
. С тех пор это было расширено, чтобы позволить фильтровать условия индекса. Однако индексы сINCLUDE
столбцами -d или индексами columnstore все еще невозможно создать для переменных таблицы.Если вы будете многократно добавлять и удалять большое количество строк в таблице, используйте
#temporary
таблицу. Это поддерживаетTRUNCATE
(что более эффективно, чемDELETE
для больших таблиц), и дополнительно последующие вставки после aTRUNCATE
могут иметь лучшую производительность, чем те, которые следуют за a,DELETE
как показано здесь .#temporary
таблицу. Это поддерживает создание статистики, которая позволяет динамически перекомпилировать план в соответствии с данными (хотя для кэшированных временных таблиц в хранимых процедурах поведение перекомпиляции необходимо понимать отдельно).SELECT
оператор, то учтите, что использование табличной переменной заблокирует возможность этого при использовании параллельного плана.#temp
таблицы внутри пользовательской блокировки транзакции могут удерживаться дольше, чем для табличных переменных (возможно, до конца транзакции или конца оператора в зависимости от типа блокировки и уровня изоляции), а также это может предотвратить усечение журналаtempdb
транзакций до тех пор, пока Пользовательская транзакция заканчивается. Так что это может способствовать использованию табличных переменных.#temporary
таблиц. Боб Уорд указывает в своейtempdb
презентации, что это может вызвать дополнительную конкуренцию системным таблицам в условиях высокого параллелизма. Кроме того, при работе с небольшими объемами данных это может существенно повлиять на производительность .Эффекты совместного использования набора строк
источник
id
и ее использованиемOPTION (RECOMPILE)
, вероятно, подойдет для этого - но протестируйте оба.Используйте переменную таблицы if для очень небольшого количества данных (тысячи байтов)
Используйте временную таблицу для большого количества данных
Еще один способ думать об этом: если вы думаете, что можете извлечь выгоду из индекса, автоматизированной статистики или какого-либо хорошего качества оптимизатора SQL, то ваш набор данных, вероятно, слишком велик для табличной переменной.
В моем примере я просто хотел поместить около 20 строк в формат и изменить их как группу, прежде чем использовать их для UPDATE / INSERT постоянной таблицы. Так что переменная таблицы идеальна.
Но я также запускаю SQL для обратного заполнения тысяч строк за раз, и я могу с уверенностью сказать, что временные таблицы работают намного лучше, чем переменные таблиц.
Это мало чем отличается от того, как CTE вызывает беспокойство по причине сходного размера - если данные в CTE очень малы, я считаю, что CTE работает так же хорошо или лучше, чем у оптимизатора, но если он достаточно большой, то тебе больно плохо
Мое понимание в основном основано на http://www.developerfusion.com/article/84397/table-variables-v-teilitary-tables-in-sql-server/ , который имеет гораздо больше деталей.
источник
Microsoft говорит здесь
источник
Я полностью согласен с Abacus (извините - не хватает очков, чтобы комментировать).
Кроме того, имейте в виду, что это не обязательно сводится к тому, сколько записей у вас есть, но к размеру ваших записей.
Например, рассматривали ли вы разницу в производительности между 1000 записей с 50 столбцами каждая против 100 000 записей только с 5 столбцами каждая?
Наконец, может быть, вы запрашиваете / храните больше данных, чем вам нужно? Вот хорошее прочтение о стратегиях оптимизации SQL . Ограничьте объем данных, которые вы извлекаете, особенно если вы не используете их все (некоторые программисты SQL становятся ленивыми и просто выбирают все, даже если они используют только небольшое подмножество). Не забывайте, что анализатор SQL-запросов также может стать вашим лучшим другом.
источник
Таблица переменных доступна только для текущего сеанса, например, если вам нужна
EXEC
другая хранимая процедура в текущем сеансе, вам придется пропустить таблицу, так как,Table Valued Parameter
конечно, это повлияет на производительность, с временными таблицами вы можете сделать это только с передача имени временной таблицыЧтобы проверить временную таблицу:
Чтобы проверить таблицу переменных:
Я испытал еще кое-что: если ваша схема не имеет
GRANT
прав для создания таблиц, используйте таблицы переменных.источник
записывая данные в объявленные таблицы
declare @tb
и после объединения с другими таблицами, я понял, что время отклика по сравнению с временными таблицамиtempdb .. # tb
намного выше.Когда я присоединяюсь к ним с помощью @tb, время для возврата результата намного больше, в отличие от #tm , возвращение происходит практически мгновенно.
Я выполнил тесты с 10 000 строк, соединяющих и соединяющих с 5 другими таблицами
источник