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


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

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

или

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

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

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

11 354

11 ответов:

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

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

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

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

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

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

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

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

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

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

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

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

еще немного чтение:

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

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

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

  1. Удачный Вставить
  2. Многорядная вставка, где оператор откатывается из-за нарушения ограничений.
  3. обновление
  4. удалить
  5. освободить

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

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

полный скрипт для воспроизведения (лучше всего запускать на экземпляре, запущенном в однопользовательском режиме и с помощью 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             |
+-----------------------+--------------------+---------------------------+---------------+------+---------------+------+------------------+

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

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

@wcm-на самом деле, чтобы NIT выбрать переменную таблицы не только ОЗУ - она может быть частично сохранена на диске.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  8. временные таблицы: хранимая процедура будет выполнять перекомпиляцию (не может использовать один и тот же план выполнения), когда мы используем переменную temp для каждого вызова sub sequent.

    переменной: если переменная не нравится.

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

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

Читать статью здесь: TempDB:: переменная таблицы vs локальная временная таблица

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

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

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

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

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

Temporary Tables versus Table Variables

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

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

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 ;

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

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

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

еще одно различие:

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

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

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

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

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

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

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

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

Переменной В Таблице

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

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

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

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