Какая разница между переменной temp и табличной переменной в SQL Server?

В SQL Server 2005 мы можем создавать временные таблицы одним из двух способов:

declare @tmp table (Col1 int, Col2 int);

или

create table #tmp (Col1 int, Col2 int);

В чем разница между этими двумя? Я прочитал противоречивые мнения о том, продолжает ли @tmp использовать tempdb, или если все происходит в памяти.

В каких сценариях выполняется одно из другого?

Ответ 1

Между временными таблицами (#tmp) и переменными таблиц (@tmp) есть несколько отличий, хотя использование tempdb не является одним из них, как указано в ссылке MSDN ниже.

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

Некоторые моменты, которые следует учитывать при выборе между ними:

  • Временные таблицы являются реальными таблицами, так что вы можете делать такие вещи, как CREATE INDEXes и т.д. Если у вас есть большие объемы данных, для которых доступ по индексу будет быстрее, тогда временные таблицы - хороший вариант.

  • Табличные переменные могут иметь индексы с помощью ограничений PRIMARY KEY или UNIQUE. (Если вам нужен неуникальный индекс, просто включите столбец первичного ключа в качестве последнего столбца в ограничении уникальности. Если у вас нет уникального столбца, вы можете использовать столбец идентификаторов.) В SQL 2014 также есть неуникальные индексы,

  • Табличные переменные не участвуют в транзакциях и SELECT неявно с NOLOCK. Поведение транзакции может быть очень полезным, например, если вы хотите выполнить ROLLBACK в середине процедуры, табличные переменные, заполненные во время этой транзакции, будут по-прежнему заполнены!

  • Временные таблицы могут привести к перекомпиляции хранимых процедур, возможно, часто. Табличные переменные не будут.

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

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

  • Использование табличных переменных в пользовательских функциях позволяет более широко использовать эти функции (подробнее см. Документацию CREATE FUNCTION). Если вы пишете функцию, вы должны использовать табличные переменные над временными таблицами, если нет острой необходимости.

  • Табличные переменные и временные таблицы хранятся в базе данных tempdb. Но в табличных переменных (с 2005 года) по умолчанию используется сопоставление текущей базы данных по сравнению с временными таблицами, которые принимают сопоставление по умолчанию для tempdb (ref). Это означает, что вы должны знать о проблемах сопоставления, если вы используете временные таблицы и ваша база данных отличается от базы данных tempdb, что создает проблемы, если вы хотите сравнить данные в временной таблице с данными в вашей базе данных.

  • Глобальные временные таблицы (## tmp) - это еще один тип временных таблиц, доступных для всех сеансов и пользователей.

Некоторое дальнейшее чтение:

Ответ 2

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

Как правило, неверно, что существует какая-либо разница в количестве каротажа (по крайней мере для операций insert/update/delete для самой таблицы, хотя у меня есть найдено, что в этом отношении существует небольшая разница для кэшированных временных объектов в хранимых процедурах из-за дополнительных обновлений системной таблицы).

Я просмотрел поведение журнала как для таблиц @table_variable, так и для #temp для следующих операций.

  • Успешная вставка
  • Multi Row Вставить, где инструкция откат из-за нарушения ограничений.
  • Update
  • Удалить
  • Освобождает

Записи журнала транзакций были почти одинаковыми для всех операций.

В версии переменной таблицы фактически есть несколько записей журнала extra, поскольку она добавляет запись (и позже удаляется) из базовой таблицы sys.syssingleobjrefs, но в целом было несколько меньше байтов, записанных исключительно как внутреннее имя для табличных переменных потребляет на 236 байтов меньше, чем для таблиц #temp (118 меньше символов nvarchar).

Полный script для воспроизведения (лучший запуск в экземпляре запускается в однопользовательском режиме и с использованием режима sqlcmd)

:setvar tablename "@T" 
:setvar tablescript "DECLARE @T TABLE"

/*
 --Uncomment this section to test a #temp table
:setvar tablename "#T" 
:setvar tablescript "CREATE TABLE #T"
*/

USE tempdb 
GO    
CHECKPOINT

DECLARE @LSN NVARCHAR(25)

SELECT @LSN = MAX([Current LSN])
FROM fn_dblog(null, null) 


EXEC(N'BEGIN TRAN StartBatch
SAVE TRAN StartBatch
COMMIT

$(tablescript)
(
[4CA996AC-C7E1-48B5-B48A-E721E7A435F0] INT PRIMARY KEY DEFAULT 0,
InRowFiller char(7000) DEFAULT ''A'',
OffRowFiller varchar(8000) DEFAULT REPLICATE(''B'',8000),
LOBFiller varchar(max) DEFAULT REPLICATE(cast(''C'' as varchar(max)),10000)
)


BEGIN TRAN InsertFirstRow
SAVE TRAN InsertFirstRow
COMMIT

INSERT INTO $(tablename)
DEFAULT VALUES

BEGIN TRAN Insert9Rows
SAVE TRAN Insert9Rows
COMMIT


INSERT INTO $(tablename) ([4CA996AC-C7E1-48B5-B48A-E721E7A435F0])
SELECT TOP 9 ROW_NUMBER() OVER (ORDER BY (SELECT 0))
FROM sys.all_columns

BEGIN TRAN InsertFailure
SAVE TRAN InsertFailure
COMMIT


/*Try and Insert 10 rows, the 10th one will cause a constraint violation*/
BEGIN TRY
INSERT INTO $(tablename) ([4CA996AC-C7E1-48B5-B48A-E721E7A435F0])
SELECT TOP (10) (10 + ROW_NUMBER() OVER (ORDER BY (SELECT 0))) % 20
FROM sys.all_columns
END TRY
BEGIN CATCH
PRINT ERROR_MESSAGE()
END CATCH

BEGIN TRAN Update10Rows
SAVE TRAN Update10Rows
COMMIT

UPDATE $(tablename)
SET InRowFiller = LOWER(InRowFiller),
    OffRowFiller  =LOWER(OffRowFiller),
    LOBFiller  =LOWER(LOBFiller)


BEGIN TRAN Delete10Rows
SAVE TRAN Delete10Rows
COMMIT

DELETE FROM  $(tablename)
BEGIN TRAN AfterDelete
SAVE TRAN AfterDelete
COMMIT

BEGIN TRAN EndBatch
SAVE TRAN EndBatch
COMMIT')


DECLARE @LSN_HEX NVARCHAR(25) = 
        CAST(CAST(CONVERT(varbinary,SUBSTRING(@LSN, 1, 8),2) AS INT) AS VARCHAR) + ':' +
        CAST(CAST(CONVERT(varbinary,SUBSTRING(@LSN, 10, 8),2) AS INT) AS VARCHAR) + ':' +
        CAST(CAST(CONVERT(varbinary,SUBSTRING(@LSN, 19, 4),2) AS INT) AS VARCHAR)        

SELECT 
    [Operation],
    [Context],
    [AllocUnitName],
    [Transaction Name],
    [Description]
FROM   fn_dblog(@LSN_HEX, null) AS D
WHERE  [Current LSN] > @LSN  

SELECT CASE
         WHEN GROUPING(Operation) = 1 THEN 'Total'
         ELSE Operation
       END AS Operation,
       Context,
       AllocUnitName,
       COALESCE(SUM([Log Record Length]), 0) AS [Size in Bytes],
       COUNT(*)                              AS Cnt
FROM   fn_dblog(@LSN_HEX, null) AS D
WHERE  [Current LSN] > @LSN  
GROUP BY GROUPING SETS((Operation, Context, AllocUnitName),())

Результаты

+-----------------------+--------------------+---------------------------+---------------+------+---------------+------+------------------+
|                       |                    |                           |             @TV      |             #TV      |                  |
+-----------------------+--------------------+---------------------------+---------------+------+---------------+------+------------------+
| Operation             | Context            | AllocUnitName             | Size in Bytes | Cnt  | Size in Bytes | Cnt  | Difference Bytes |
+-----------------------+--------------------+---------------------------+---------------+------+---------------+------+------------------+
| LOP_ABORT_XACT        | LCX_NULL           |                           | 52            | 1    | 52            | 1    |                  |
| LOP_BEGIN_XACT        | LCX_NULL           |                           | 6056          | 50   | 6056          | 50   |                  |
| LOP_COMMIT_XACT       | LCX_NULL           |                           | 2548          | 49   | 2548          | 49   |                  |
| LOP_COUNT_DELTA       | LCX_CLUSTERED      | sys.sysallocunits.clust   | 624           | 3    | 624           | 3    |                  |
| LOP_COUNT_DELTA       | LCX_CLUSTERED      | sys.sysrowsets.clust      | 208           | 1    | 208           | 1    |                  |
| LOP_COUNT_DELTA       | LCX_CLUSTERED      | sys.sysrscols.clst        | 832           | 4    | 832           | 4    |                  |
| LOP_CREATE_ALLOCCHAIN | LCX_NULL           |                           | 120           | 3    | 120           | 3    |                  |
| LOP_DELETE_ROWS       | LCX_INDEX_INTERIOR | Unknown Alloc Unit        | 720           | 9    | 720           | 9    |                  |
| LOP_DELETE_ROWS       | LCX_MARK_AS_GHOST  | sys.sysallocunits.clust   | 444           | 3    | 444           | 3    |                  |
| LOP_DELETE_ROWS       | LCX_MARK_AS_GHOST  | sys.sysallocunits.nc      | 276           | 3    | 276           | 3    |                  |
| LOP_DELETE_ROWS       | LCX_MARK_AS_GHOST  | sys.syscolpars.clst       | 628           | 4    | 628           | 4    |                  |
| LOP_DELETE_ROWS       | LCX_MARK_AS_GHOST  | sys.syscolpars.nc         | 484           | 4    | 484           | 4    |                  |
| LOP_DELETE_ROWS       | LCX_MARK_AS_GHOST  | sys.sysidxstats.clst      | 176           | 1    | 176           | 1    |                  |
| LOP_DELETE_ROWS       | LCX_MARK_AS_GHOST  | sys.sysidxstats.nc        | 144           | 1    | 144           | 1    |                  |
| LOP_DELETE_ROWS       | LCX_MARK_AS_GHOST  | sys.sysiscols.clst        | 100           | 1    | 100           | 1    |                  |
| LOP_DELETE_ROWS       | LCX_MARK_AS_GHOST  | sys.sysiscols.nc1         | 88            | 1    | 88            | 1    |                  |
| LOP_DELETE_ROWS       | LCX_MARK_AS_GHOST  | sys.sysobjvalues.clst     | 596           | 5    | 596           | 5    |                  |
| LOP_DELETE_ROWS       | LCX_MARK_AS_GHOST  | sys.sysrowsets.clust      | 132           | 1    | 132           | 1    |                  |
| LOP_DELETE_ROWS       | LCX_MARK_AS_GHOST  | sys.sysrscols.clst        | 528           | 4    | 528           | 4    |                  |
| LOP_DELETE_ROWS       | LCX_MARK_AS_GHOST  | sys.sysschobjs.clst       | 1040          | 6    | 1276          | 6    | 236              |
| LOP_DELETE_ROWS       | LCX_MARK_AS_GHOST  | sys.sysschobjs.nc1        | 820           | 6    | 1060          | 6    | 240              |
| LOP_DELETE_ROWS       | LCX_MARK_AS_GHOST  | sys.sysschobjs.nc2        | 820           | 6    | 1060          | 6    | 240              |
| LOP_DELETE_ROWS       | LCX_MARK_AS_GHOST  | sys.sysschobjs.nc3        | 480           | 6    | 480           | 6    |                  |
| LOP_DELETE_ROWS       | LCX_MARK_AS_GHOST  | sys.syssingleobjrefs.clst | 96            | 1    |               |      | -96              |
| LOP_DELETE_ROWS       | LCX_MARK_AS_GHOST  | sys.syssingleobjrefs.nc1  | 88            | 1    |               |      | -88              |
| LOP_DELETE_ROWS       | LCX_MARK_AS_GHOST  | Unknown Alloc Unit        | 72092         | 19   | 72092         | 19   |                  |
| LOP_DELETE_ROWS       | LCX_TEXT_MIX       | Unknown Alloc Unit        | 16348         | 37   | 16348         | 37   |                  |
| LOP_FORMAT_PAGE       | LCX_HEAP           | Unknown Alloc Unit        | 1596          | 19   | 1596          | 19   |                  |
| LOP_FORMAT_PAGE       | LCX_IAM            | Unknown Alloc Unit        | 252           | 3    | 252           | 3    |                  |
| LOP_FORMAT_PAGE       | LCX_INDEX_INTERIOR | Unknown Alloc Unit        | 84            | 1    | 84            | 1    |                  |
| LOP_FORMAT_PAGE       | LCX_TEXT_MIX       | Unknown Alloc Unit        | 4788          | 57   | 4788          | 57   |                  |
| LOP_HOBT_DDL          | LCX_NULL           |                           | 108           | 3    | 108           | 3    |                  |
| LOP_HOBT_DELTA        | LCX_NULL           |                           | 9600          | 150  | 9600          | 150  |                  |
| LOP_INSERT_ROWS       | LCX_CLUSTERED      | sys.sysallocunits.clust   | 456           | 3    | 456           | 3    |                  |
| LOP_INSERT_ROWS       | LCX_CLUSTERED      | sys.syscolpars.clst       | 644           | 4    | 644           | 4    |                  |
| LOP_INSERT_ROWS       | LCX_CLUSTERED      | sys.sysidxstats.clst      | 180           | 1    | 180           | 1    |                  |
| LOP_INSERT_ROWS       | LCX_CLUSTERED      | sys.sysiscols.clst        | 104           | 1    | 104           | 1    |                  |
| LOP_INSERT_ROWS       | LCX_CLUSTERED      | sys.sysobjvalues.clst     | 616           | 5    | 616           | 5    |                  |
| LOP_INSERT_ROWS       | LCX_CLUSTERED      | sys.sysrowsets.clust      | 136           | 1    | 136           | 1    |                  |
| LOP_INSERT_ROWS       | LCX_CLUSTERED      | sys.sysrscols.clst        | 544           | 4    | 544           | 4    |                  |
| LOP_INSERT_ROWS       | LCX_CLUSTERED      | sys.sysschobjs.clst       | 1064          | 6    | 1300          | 6    | 236              |
| LOP_INSERT_ROWS       | LCX_CLUSTERED      | sys.syssingleobjrefs.clst | 100           | 1    |               |      | -100             |
| LOP_INSERT_ROWS       | LCX_CLUSTERED      | Unknown Alloc Unit        | 135888        | 19   | 135888        | 19   |                  |
| LOP_INSERT_ROWS       | LCX_INDEX_INTERIOR | Unknown Alloc Unit        | 1596          | 19   | 1596          | 19   |                  |
| LOP_INSERT_ROWS       | LCX_INDEX_LEAF     | sys.sysallocunits.nc      | 288           | 3    | 288           | 3    |                  |
| LOP_INSERT_ROWS       | LCX_INDEX_LEAF     | sys.syscolpars.nc         | 500           | 4    | 500           | 4    |                  |
| LOP_INSERT_ROWS       | LCX_INDEX_LEAF     | sys.sysidxstats.nc        | 148           | 1    | 148           | 1    |                  |
| LOP_INSERT_ROWS       | LCX_INDEX_LEAF     | sys.sysiscols.nc1         | 92            | 1    | 92            | 1    |                  |
| LOP_INSERT_ROWS       | LCX_INDEX_LEAF     | sys.sysschobjs.nc1        | 844           | 6    | 1084          | 6    | 240              |
| LOP_INSERT_ROWS       | LCX_INDEX_LEAF     | sys.sysschobjs.nc2        | 844           | 6    | 1084          | 6    | 240              |
| LOP_INSERT_ROWS       | LCX_INDEX_LEAF     | sys.sysschobjs.nc3        | 504           | 6    | 504           | 6    |                  |
| LOP_INSERT_ROWS       | LCX_INDEX_LEAF     | sys.syssingleobjrefs.nc1  | 92            | 1    |               |      | -92              |
| LOP_INSERT_ROWS       | LCX_TEXT_MIX       | Unknown Alloc Unit        | 5112          | 71   | 5112          | 71   |                  |
| LOP_MARK_SAVEPOINT    | LCX_NULL           |                           | 508           | 8    | 508           | 8    |                  |
| LOP_MODIFY_COLUMNS    | LCX_CLUSTERED      | Unknown Alloc Unit        | 1560          | 10   | 1560          | 10   |                  |
| LOP_MODIFY_HEADER     | LCX_HEAP           | Unknown Alloc Unit        | 3780          | 45   | 3780          | 45   |                  |
| LOP_MODIFY_ROW        | LCX_CLUSTERED      | sys.syscolpars.clst       | 384           | 4    | 384           | 4    |                  |
| LOP_MODIFY_ROW        | LCX_CLUSTERED      | sys.sysidxstats.clst      | 100           | 1    | 100           | 1    |                  |
| LOP_MODIFY_ROW        | LCX_CLUSTERED      | sys.sysrowsets.clust      | 92            | 1    | 92            | 1    |                  |
| LOP_MODIFY_ROW        | LCX_CLUSTERED      | sys.sysschobjs.clst       | 1144          | 13   | 1144          | 13   |                  |
| LOP_MODIFY_ROW        | LCX_IAM            | Unknown Alloc Unit        | 4224          | 48   | 4224          | 48   |                  |
| LOP_MODIFY_ROW        | LCX_PFS            | Unknown Alloc Unit        | 13632         | 169  | 13632         | 169  |                  |
| LOP_MODIFY_ROW        | LCX_TEXT_MIX       | Unknown Alloc Unit        | 108640        | 120  | 108640        | 120  |                  |
| LOP_ROOT_CHANGE       | LCX_CLUSTERED      | sys.sysallocunits.clust   | 960           | 10   | 960           | 10   |                  |
| LOP_SET_BITS          | LCX_GAM            | Unknown Alloc Unit        | 1200          | 20   | 1200          | 20   |                  |
| LOP_SET_BITS          | LCX_IAM            | Unknown Alloc Unit        | 1080          | 18   | 1080          | 18   |                  |
| LOP_SET_BITS          | LCX_SGAM           | Unknown Alloc Unit        | 120           | 2    | 120           | 2    |                  |
| LOP_SHRINK_NOOP       | LCX_NULL           |                           |               |      | 32            | 1    | 32               |
+-----------------------+--------------------+---------------------------+---------------+------+---------------+------+------------------+
| Total                 |                    |                           | 410144        | 1095 | 411232        | 1092 | 1088             |
+-----------------------+--------------------+---------------------------+---------------+------+---------------+------+------------------+

Ответ 3

В каких сценариях выполняется одно из других?

Для меньших таблиц (менее 1000 строк) используйте временную переменную, в противном случае используйте временную таблицу.

Ответ 4

@wcm - на самом деле, чтобы выбрать таблицу, переменная таблицы не только Рам - ее можно частично сохранить на диске.

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

Хорошая справочная статья

Ответ 5

  • Таблица Temp: таблицу Temp легко создавать и архивировать данные.

    Переменная таблицы: Но переменная таблицы связана с усилием, когда мы обычно создаем обычные таблицы.

  • Таблица Temp: результат таблицы Temp может использоваться несколькими пользователями.

    Таблица: переменная таблицы может использоваться только текущим пользователем.

  • Таблица Temp: таблица temp будет храниться в tempdb. Это сделает сетевой трафик. Когда у нас есть большие данные в таблице temp, он должен работать через базу данных. Проблема с производительностью будет существовать.

    Таблица: переменная таблицы хранится в физической памяти для некоторых данных, а затем, когда размер увеличивается, он будет перемещен в tempdb.

  • Таблица Temp: таблица Temp может выполнять все операции DDL. Он позволяет создавать индексы, отбрасывать, изменять и т.д.,

    Таблица: переменная таблицы не позволяет выполнять операции DDL. Но переменная таблицы позволяет нам создавать только кластерный индекс.

  • Таблица Temp: таблица Temp может использоваться для текущего сеанса или глобальной. Чтобы сеанс нескольких пользователей мог использовать результаты в таблице.

    Переменная таблицы: Но переменную таблицы можно использовать до этой программы. (Хранимая процедура)

  • Таблица Temp: переменная Temp не может использовать транзакции. Когда мы выполняем операции DML с временной таблицей, это может быть откат или фиксация транзакций.

    Переменная таблицы: Но мы не можем это сделать для переменной таблицы.

  • Таблица Temp: функции не могут использовать временную переменную. Более того, мы не можем выполнять операцию DML в функциях.

    Переменная таблицы: Но функция позволяет использовать переменную таблицы. Но используя переменную таблицы, мы можем это сделать.

  • Таблица Temp: хранимая процедура выполняет перекомпиляцию (не может использовать тот же план выполнения), когда мы используем временную переменную для каждого последующего вызова.

    Переменная таблицы: в то время как переменная таблицы не будет работать так.

Ответ 6

Для всех вас, кто верит в миф о том, что временные переменные находятся только в памяти

Во-первых, переменная таблицы НЕ обязательно является резидентной. Под давлением памяти страницы, принадлежащие переменной таблицы, могут быть вытолкнуты в tempdb.

Прочитайте статью здесь: TempDB:: Таблица переменной vs локальная временная таблица

Ответ 7

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

Ответ 8

Цитата взята из; Профессиональные внутренние компоненты SQL Server 2012 и устранение неполадок

Статистика Основное различие между временными таблицами и табличными переменными состоит в том, что статистика не создается для табличных переменных. Это имеет два основных следствия, первое из которых заключается в том, что Оптимизатор запросов использует фиксированную оценку для числа строк в табличной переменной независимо от содержащихся в ней данных. Более того, добавление или удаление данных не меняет оценку.

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

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

Temporary Tables versus Table Variables

ПЕРЕМЕННЫЕ ТАБЛИЦЫ НЕ СОЗДАЮТСЯ В ПАМЯТИ

Существует распространенное заблуждение, что табличные переменные являются структурами в памяти и поэтому будут работать быстрее, чем временные таблицы. Благодаря DMV под названием sys. Использование dm _ db _ session _ space _, которое показывает использование tempdb сессией, вы можете доказать, что это не так. После перезапуска SQL Server для очистки DMV запустите следующий сценарий, чтобы подтвердить, что идентификатор сеанса _ возвращает 0 для пользователя _ объекты _ alloc _ page _ count:

SELECT session_id,
database_id,
user_objects_alloc_page_count
FROM sys.dm_db_session_space_usage
WHERE session_id > 50 ;

Теперь вы можете проверить, сколько места занимает временная таблица, запустив следующий скрипт, чтобы создать временную таблицу с одним столбцом и заполнить ее одной строкой:

CREATE TABLE #TempTable ( ID INT ) ;
INSERT INTO #TempTable ( ID )
VALUES ( 1 ) ;
GO
SELECT session_id,
database_id,
user_objects_alloc_page_count
FROM sys.dm_db_session_space_usage
WHERE session_id > 50 ;

Результаты на моем сервере показывают, что таблице была выделена одна страница в базе данных tempdb. Теперь запустите тот же скрипт, но на этот раз используйте табличную переменную:

DECLARE @TempTable TABLE ( ID INT ) ;
INSERT INTO @TempTable ( ID )
VALUES ( 1 ) ;
GO
SELECT session_id,
database_id,
user_objects_alloc_page_count
FROM sys.dm_db_session_space_usage
WHERE session_id > 50 ;

Какой использовать?

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

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

Ответ 9

Другое отличие:

Таблицу var можно получить только из операторов внутри процедуры, которая ее создает, а не из других процедур, вызываемых этой процедурой, или вложенного динамического SQL (через exec или sp_executesql).

С другой стороны, область temp table включает код в вызываемых процедурах и вложенный динамический SQL.

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

Ответ 10

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

Ответ 11

Временная таблица

Временная таблица ведет себя как реальные таблицы, но создается во время выполнения. Его работа похожа на реальную таблицу. Мы можем делать почти все операции, которые возможны в реальных таблицах. Мы можем использовать DDL-выражения, такие как ALTER, CREATE, DROP на временных таблицах.

Любые изменения в структуре Временной таблицы возможны после создания. Временная таблица хранится в базе данных системных баз данных tempdb.

Временная таблица участвует в транзакциях, протоколировании или блокировке. По этой причине он медленнее, чем Table Variable.

Переменная таблицы

Его переменная, но работает как таблица. Он также создан в базе данных Tempdb не в памяти. Переменная таблицы доступна только в пакетной или хранимой процедуре. Вам не нужно отбрасывать таблицу Variable, ее автоматически отбрасывается при пакетной обработке и хранении процесса завершения процедуры

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

Переменные таблицы не участвуют в транзакциях, протоколировании или блокировке. Транзакции, протоколирование и блокировка не влияют на переменные таблицы.

Прочтите эту статью для более - http://goo.gl/GXtXqz