В SQL Server 2005 мы можем создавать временные таблицы одним из двух способов:
declare @tmp table (Col1 int, Col2 int);
или
create table #tmp (Col1 int, Col2 int);
Каковы различия между этими двумя? Я прочитал противоречивые мнения о том, использует ли @tmp все еще tempdb, или все происходит в памяти.
В каких случаях один превосходит другой?
sql-server
temp-tables
table-variable
Эрик З Борода
источник
источник
Ответы:
Между временными таблицами (#tmp) и переменными таблиц (@tmp) есть несколько отличий, хотя использование tempdb не является одним из них, как указано в ссылке MSDN ниже.
Как правило, для небольших и средних объемов данных и простых сценариев использования следует использовать табличные переменные. (Это слишком широкое руководство, конечно, с множеством исключений - см. Ниже и в следующих статьях.)
Некоторые моменты, которые следует учитывать при выборе между ними:
Временные таблицы являются реальными таблицами, поэтому вы можете делать такие вещи, как CREATE INDEXes и т. Д. Если у вас есть большие объемы данных, для которых доступ по индексу будет быстрее, тогда временные таблицы - хороший вариант.
Табличные переменные могут иметь индексы с помощью ограничений PRIMARY KEY или UNIQUE. (Если вам нужен неуникальный индекс, просто включите столбец первичного ключа в качестве последнего столбца в ограничении уникальности. Если у вас нет уникального столбца, вы можете использовать столбец идентификаторов.) В SQL 2014 также есть неуникальные индексы ,
Табличные переменные не участвуют в транзакциях, а
SELECT
s неявно сNOLOCK
. Поведение транзакции может быть очень полезным, например, если вы хотите выполнить ROLLBACK в середине процедуры, табличные переменные, заполненные во время этой транзакции, будут по-прежнему заполнены!Временные таблицы могут привести к перекомпиляции хранимых процедур, возможно, часто. Табличные переменные не будут.
Вы можете создать временную таблицу с помощью SELECT INTO, которая может быть быстрее написана (хорошо для специальных запросов) и может позволить вам иметь дело с изменением типов данных с течением времени, так как вам не нужно заранее определять структуру временной таблицы.
Вы можете передавать табличные переменные обратно из функций, что позволяет вам гораздо проще инкапсулировать и повторно использовать логику (например, сделать функцию для разбиения строки в таблицу значений на некотором произвольном разделителе).
Использование табличных переменных в пользовательских функциях позволяет более широко использовать эти функции (подробнее см. Документацию CREATE FUNCTION). Если вы пишете функцию, вы должны использовать табличные переменные над временными таблицами, если нет острой необходимости.
Табличные переменные и временные таблицы хранятся в базе данных tempdb. Но для табличных переменных (с 2005 года) по умолчанию используется сопоставление текущей базы данных по сравнению с временными таблицами, которые принимают сопоставление по умолчанию для базы данных tempdb ( ref ). Это означает, что вы должны знать о проблемах сопоставления, если вы используете временные таблицы и ваша база данных отличается от базы данных tempdb, что создает проблемы, если вы хотите сравнить данные в временной таблице с данными в вашей базе данных.
Глобальные временные таблицы (## tmp) - это еще один тип временных таблиц, доступных для всех сеансов и пользователей.
Некоторое дальнейшее чтение:
Великий ответ Мартина Смита на dba.stackexchange.com
MSDN FAQ по разнице между ними: https://support.microsoft.com/en-gb/kb/305977
Статья в блоге MDSN: https://docs.microsoft.com/archive/blogs/sqlserverstorageengine/tempdb-table-variable-vs-local-tevent-table
Статья: https://searchsqlserver.techtarget.com/tip/Teilitary-tables-in-SQL-Server-vs-table-variables
Неожиданное поведение и влияние на производительность временных таблиц и временных переменных: Пол Уайт на SQLblog.com
источник
Просто посмотрите на утверждение в принятом ответе, что переменные таблицы не участвуют в ведении журнала.
Как правило, не соответствует действительности, что есть какое-либо различие в количестве журналирования (по крайней мере для
insert
/update
/delete
операций к самой таблице, хотя я с тех пор нашел что существует небольшая разница в этом отношении для кэшированных временных объектов в хранимых процедурах из-за дополнительной системной таблицы обновления).Я посмотрел на поведение журналирования как
@table_variable
для#temp
таблицы a, так и для следующих операций.Записи журнала транзакций были практически идентичны для всех операций.
Версия табличной переменной на самом деле имеет несколько дополнительных записей журнала, потому что она получает запись, добавляемую (а затем удаляемую) из
sys.syssingleobjrefs
базовой таблицы, но в целом было зарегистрировано лишь несколько меньших байтов, поскольку внутреннее имя для переменных таблицы потребляет на 236 меньше байтов, чем для#temp
таблиц. (118nvarchar
символов меньше ).Полный сценарий для воспроизведения (лучший запуск на экземпляре, запущенном в однопользовательском режиме и
sqlcmd
режиме использования )Результаты
источник
INSERT ... SELECT
не были минимально зарегистрированы, и вы не можетеSELECT INTO ...
использовать табличную переменную.Для небольших таблиц (менее 1000 строк) используйте временную переменную, в противном случае используйте временную таблицу.
источник
@wcm - фактически, чтобы выбрать переменную Table Variable не только Ram - она может быть частично сохранена на диске.
Временная таблица может иметь индексы, тогда как переменная таблицы может иметь только первичный индекс. Если скорость является проблемой, переменные таблицы могут быть быстрее, но, очевидно, если имеется много записей или требуется поиск во временной таблице кластерного индекса, тогда лучше использовать временную таблицу.
Хорошая справочная статья
источник
Временная таблица: Временную таблицу легко создавать и создавать резервные копии данных.
Переменная таблицы: но переменная таблицы требует усилий, когда мы обычно создаем обычные таблицы.
Временная таблица: результат временной таблицы может использоваться несколькими пользователями.
Переменная таблицы: но переменная таблицы может использоваться только текущим пользователем.
Temp table: временная таблица будет храниться в базе данных tempdb. Это сделает сетевой трафик. Когда у нас есть большие данные во временной таблице, они должны работать по всей базе данных. Проблема с производительностью будет существовать.
Табличная переменная: Но табличная переменная будет хранить в физической памяти некоторые данные, а затем, когда размер увеличится, она будет перемещена в базу данных tempdb.
Временная таблица: Временная таблица может выполнять все операции DDL. Позволяет создавать индексы, отбрасывать, изменять и т. Д.,
Табличная переменная: В то время как табличная переменная не позволяет выполнять операции DDL. Но табличная переменная позволяет нам создавать только кластерный индекс.
Временная таблица: Временная таблица может использоваться для текущего сеанса или глобального. Так что многопользовательский сеанс может использовать результаты в таблице.
Табличная переменная: но табличная переменная может использоваться до этой программы. (Хранимая процедура)
Таблица Temp: переменная Temp не может использовать транзакции. Когда мы выполняем операции DML с временной таблицей, это может быть откат или фиксация транзакций.
Табличная переменная: Но мы не можем сделать это для табличной переменной.
Таблица Temp: Функции не могут использовать переменную temp. Более того, мы не можем выполнять операции DML в функциях.
Переменная таблицы: Но функция позволяет нам использовать переменную таблицы. Но используя переменную таблицы, мы можем это сделать.
Таблица Temp: хранимая процедура будет выполнять перекомпиляцию (не может использовать тот же план выполнения), когда мы используем переменную temp для каждого последующего вызова.
Переменная таблицы: в то время как переменная таблицы не будет так делать.
источник
Для всех, кто верит в миф о том, что временные переменные находятся только в памяти
Во-первых, переменная таблицы НЕ обязательно должна быть резидентной. Под давлением памяти страницы, принадлежащие табличной переменной, могут быть перенесены в базу данных tempdb.
Прочитайте статью здесь: TempDB :: Переменная таблицы против локальной временной таблицы
источник
Другое основное отличие состоит в том, что у табличных переменных нет статистики по столбцам, в отличие от временных таблиц. Это означает, что оптимизатор запросов не знает, сколько строк находится в табличной переменной (он угадывает 1), что может привести к генерации крайне неоптимальных планов, если переменная таблицы на самом деле имеет большое количество строк.
источник
rows
Столбецsys.partitions
поддерживается для таблицы переменных , так что на самом деле знает , сколько строк в таблице. Это можно увидеть с помощьюOPTION (RECOMPILE)
. Но отсутствие статистики по столбцам означает, что он не может оценить конкретные предикаты столбцов.Цитата взята из; Профессиональные внутренние компоненты SQL Server 2012 и устранение неполадок
ПЕРЕМЕННЫЕ ТАБЛИЦЫ НЕ СОЗДАЮТСЯ В ПАМЯТИ
Существует распространенное заблуждение, что табличные переменные являются структурами в памяти и поэтому будут работать быстрее, чем временные таблицы . Благодаря DMV под названием sys. Использование dm _ db _ session _ space _, которое показывает использование tempdb сессией, вы можете доказать, что это не так . После перезапуска SQL Server для очистки DMV запустите следующий сценарий, чтобы подтвердить, что идентификатор сеанса _ возвращает 0 для пользователя _ объекты _ alloc _ page _ count:
Теперь вы можете проверить, сколько места занимает временная таблица, запустив следующий скрипт, чтобы создать временную таблицу с одним столбцом и заполнить ее одной строкой:
Результаты на моем сервере показывают, что таблице была выделена одна страница в базе данных tempdb. Теперь запустите тот же скрипт, но на этот раз используйте табличную переменную:
Какой использовать?
источник
Еще одно отличие:
Доступ к таблице var возможен только из операторов внутри процедуры, которая ее создает, но не из других процедур, вызываемых этой процедурой или вложенного динамического SQL (через exec или sp_executesql).
Область временных таблиц, с другой стороны, включает код в вызываемых процедурах и вложенный динамический SQL.
Если таблица, созданная вашей процедурой, должна быть доступна из других вызываемых процедур или динамического SQL, вы должны использовать временную таблицу. Это может быть очень удобно в сложных ситуациях.
источник
Различия между
Temporary Tables (##temp/#temp)
иTable Variables (@table)
как:Table variable (@table)
создается вmemory
. Принимая во внимание, чтоTemporary table (##temp/#temp)
создается вtempdb database
. Однако, если есть нехватка памяти, страницы, принадлежащие табличной переменной, могут быть помещены в tempdb.Table variables
не может быть вовлечен вtransactions, logging or locking
. Это делает@table faster then #temp
. Таким образом, переменная таблицы быстрее, чем временная таблица.Temporary table
допускает модификации схемы в отличие отTable variables
.Temporary tables
видны в созданной подпрограмме, а также в дочерних подпрограммах. Принимая во внимание, что переменные таблицы видны только в созданной подпрограмме.Temporary tables
разрешены,CREATE INDEXes
тогда как,Table variables
не разрешены,CREATE INDEX
вместо этого они могут иметь индекс с помощьюPrimary Key or Unique Constraint
.источник
Также учтите, что вы часто можете заменить обе таблицы производными таблицами, что также может быть быстрее. Однако, как и при любой настройке производительности, только реальные тесты на основе ваших реальных данных могут предложить вам лучший подход для вашего конкретного запроса.
источник
Меня удивляет, что никто не упомянул ключевое различие между этими двумя в том, что временная таблица поддерживает параллельную вставку, а переменная таблицы - нет. Вы должны увидеть разницу с планом выполнения. А вот видео с семинаров по SQL на 9 канале .
Это также объясняет, почему вы должны использовать временную переменную для небольших таблиц, в противном случае используйте временную таблицу, как SQLMenace отвечал ранее.
источник