Domanda

In SQL Server 2005, possiamo creare tabelle temporanee in due modi:

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

O

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

Quali sono le differenze tra questi due?Ho letto opinioni contrastanti sul fatto che @tmp utilizzi ancora tempdb o se tutto accade in memoria.

In quali scenari uno supera l’altro?

È stato utile?

Soluzione

Esistono alcune differenze tra le tabelle temporanee (#tmp) e le variabili di tabella (@tmp), sebbene l'utilizzo di tempdb non sia una di queste, come spiegato nel collegamento MSDN di seguito.

Come regola generale, per volumi di dati da piccoli a medi e scenari di utilizzo semplici è necessario utilizzare variabili di tabella.(Questa è una linea guida eccessivamente ampia con ovviamente molte eccezioni - vedere sotto e gli articoli successivi.)

Alcuni punti da considerare quando si sceglie tra loro:

  • Le tabelle temporanee sono tabelle reali quindi puoi fare cose come CREARE INDICI, ecc.Se disponi di grandi quantità di dati per i quali l'accesso tramite indice sarà più veloce, le tabelle temporanee sono una buona opzione.

  • Le variabili di tabella possono avere indici utilizzando i vincoli PRIMARY KEY o UNIQUE.(Se desideri un indice non univoco, includi semplicemente la colonna della chiave primaria come ultima colonna nel vincolo univoco.Se non disponi di una colonna univoca, puoi utilizzare una colonna Identity.) SQL 2014 ha anche indici non univoci.

  • Le variabili di tabella non partecipano alle transazioni e SELECTs sono implicitamente con NOLOCK.Il comportamento della transazione può essere molto utile, ad esempio se si desidera eseguire il ROLLBACK a metà di una procedura, le variabili della tabella popolate durante quella transazione verranno comunque popolate!

  • Le tabelle temporanee potrebbero comportare la ricompilazione delle procedure memorizzate, forse spesso.Le variabili di tabella no.

  • Puoi creare una tabella temporanea utilizzando SELECT INTO, che può essere più veloce da scrivere (utile per query ad hoc) e potrebbe consentirti di gestire la modifica dei tipi di dati nel tempo, poiché non è necessario definire in anticipo la struttura della tabella temporanea.

  • È possibile restituire variabili di tabella dalle funzioni, consentendo di incapsulare e riutilizzare la logica molto più facilmente (ad esempio, creare una funzione per dividere una stringa in una tabella di valori su un delimitatore arbitrario).

  • L'utilizzo delle variabili di tabella all'interno delle funzioni definite dall'utente consente a tali funzioni di essere utilizzate più ampiamente (vedere la documentazione CREATE FUNCTION per i dettagli).Se stai scrivendo una funzione dovresti utilizzare variabili di tabella su tabelle temporanee a meno che non ci sia altrimenti una necessità impellente.

  • Sia le variabili di tabella che le tabelle temporanee sono archiviate in tempdb.Ma le variabili di tabella (dal 2005) utilizzano per impostazione predefinita le regole di confronto del database corrente rispetto alle tabelle temporanee che accettano le regole di confronto predefinite di tempdb (rif).Ciò significa che dovresti essere consapevole dei problemi di confronto se usi tabelle temporanee e il tuo confronto db è diverso da quello di tempdb, causando problemi se desideri confrontare i dati nella tabella temporanea con i dati nel tuo database.

  • Le tabelle temporanee globali (##tmp) sono un altro tipo di tabella temporanea disponibile per tutte le sessioni e tutti gli utenti.

Alcune ulteriori letture:

Altri suggerimenti

Basta guardare l'affermazione nella risposta accettata secondo cui le variabili di tabella non partecipano alla registrazione.

Sembra generalmente falso che ci sia qualche differenza nella quantità di logging (almeno per insert/update/delete operazioni al tavolo stesso anche se ho da allora trovato che esiste qualche piccola differenza a questo riguardo per gli oggetti temporanei memorizzati nella cache nelle procedure memorizzate a causa di ulteriori aggiornamenti della tabella di sistema).

Ho esaminato il comportamento di registrazione rispetto a a @table_variable e un #temp tabella per le operazioni successive.

  1. Inserimento riuscito
  2. Inserimento di più righe in cui l'istruzione è stata ripristinata a causa della violazione del vincolo.
  3. Aggiornamento
  4. Eliminare
  5. Deallocare

I record del registro delle transazioni erano quasi identici per tutte le operazioni.

La versione delle variabili di tabella in realtà ne ha alcune extra log perché viene aggiunta una voce (e successivamente rimossa da) al file sys.syssingleobjrefs tabella di base ma nel complesso sono stati registrati alcuni byte in meno semplicemente poiché il nome interno per le variabili di tabella consuma 236 byte in meno rispetto a #temp tavoli (118 in meno nvarchar caratteri).

Script completo da riprodurre (è meglio eseguirlo su un'istanza avviata in modalità utente singolo e utilizzando sqlcmd modalità)

: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),())

Risultati

+-----------------------+--------------------+---------------------------+---------------+------+---------------+------+------------------+
|                       |                    |                           |             @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             |
+-----------------------+--------------------+---------------------------+---------------+------+---------------+------+------------------+

In quali scenari uno supera l’altro?

Per le tabelle più piccole (meno di 1000 righe) utilizzare una variabile temporanea, altrimenti utilizzare una tabella temporanea.

@wcm - in realtà per scegliere la variabile della tabella non è solo Ram - può essere parzialmente memorizzata su disco.

Una tabella temporanea può avere indici, mentre una variabile di tabella può avere solo un indice primario.Se la velocità è un problema Le variabili di tabella possono essere più veloci, ma ovviamente se sono presenti molti record o è necessario eseguire la ricerca nella tabella temporanea di un indice cluster, allora una tabella temporanea sarebbe migliore.

Buon articolo di fondo

  1. Tabella temporanea:È facile creare una tabella temporanea ed eseguire il backup dei dati.

    Variabile della tabella:Ma la variabile table comporta lo sforzo quando solitamente creiamo le tabelle normali.

  2. Tabella temporanea:Il risultato della tabella temporanea può essere utilizzato da più utenti.

    Variabile della tabella:Ma la variabile table può essere utilizzata solo dall'utente corrente.

  3. Tabella temporanea:La tabella temporanea verrà archiviata nel tempdb.Farà traffico di rete.Quando abbiamo dati di grandi dimensioni nella tabella temporanea, devono funzionare in tutto il database.Esisterà un problema di prestazioni.

    Variabile della tabella:Ma una variabile di tabella memorizzerà nella memoria fisica alcuni dati, quindi in seguito, quando la dimensione aumenterà, verrà spostata nel tempdb.

  4. Tabella temporanea:La tabella temporanea può eseguire tutte le operazioni DDL.Permette di creare indici, eliminare, alterare, ecc.,

    Variabile della tabella:Considerando che la variabile di tabella non consentirà di eseguire le operazioni DDL.Ma la variabile table ci consente di creare solo l'indice cluster.

  5. Tabella temporanea:La tabella temporanea può essere utilizzata per la sessione corrente o globale.In modo che una sessione con più utenti possa utilizzare i risultati nella tabella.

    Variabile della tabella:Ma la variabile table può essere utilizzata fino a quel programma.(Procedura memorizzata)

  6. Tabella temporanea:La variabile temporanea non può utilizzare le transazioni.Quando eseguiamo le operazioni DML con la tabella temporanea, è possibile eseguire il rollback o il commit delle transazioni.

    Variabile della tabella:Ma non possiamo farlo per la variabile di tabella.

  7. Tabella temporanea:Le funzioni non possono utilizzare la variabile temp.Inoltre non possiamo eseguire l'operazione DML nelle funzioni .

    Variabile della tabella:Ma la funzione ci consente di utilizzare la variabile table.Ma usando la variabile table possiamo farlo.

  8. Tabella temporanea:La procedura memorizzata eseguirà la ricompilazione (non può utilizzare lo stesso piano di esecuzione) quando utilizziamo la variabile temp per ogni chiamata successiva.

    Variabile della tabella:Mentre la variabile table non farà così.

Per tutti voi che credete al mito secondo cui le variabili temporanee sono solo nella memoria

Innanzitutto, la variabile della tabella NON è necessariamente residente in memoria.Sotto pressione della memoria, le pagine appartenenti a una variabile di tabella possono essere inviate a tempdb.

Leggi l'articolo qui: DB temporaneo::Variabile di tabella e tabella temporanea locale

L'altra differenza principale è che le variabili di tabella non hanno statistiche di colonna, come invece fanno le tabelle temporanee.Ciò significa che l'ottimizzatore di query non sa quante righe sono presenti nella variabile di tabella (indovina 1), il che può portare alla generazione di piani altamente non ottimali se la variabile di tabella ha effettivamente un numero elevato di righe.

Citazione tratta da; Componenti interni e risoluzione dei problemi di SQL Server 2012 professionale

StatisticheLa differenza principale tra le tabelle della temperatura e le variabili della tabella è che le statistiche non sono create sulle variabili della tabella.Ciò ha due conseguenze importanti, la prima delle quali è che l'ottimizzatore di query utilizza una stima FI XED per il numero di righe in una variabile della tabella indipendentemente dai dati che contiene.Inoltre, l'aggiunta o la rimozione dei dati non modifica la stima.

Indici Non è possibile creare indici sulle variabili della tabella sebbene sia possibile creare vincoli.Ciò significa che, creando chiavi primarie o vincoli univoci, è possibile avere indici (poiché questi vengono creati per supportare i vincoli) sulle variabili della tabella.Anche se hai vincoli e quindi indici che avranno statistiche, gli indici non verranno utilizzati quando la query viene compilata perché non esisteranno al momento della compilazione, né causano ricompilazioni.

Modifiche allo schema Le modifiche allo schema sono possibili su tabelle temporanee ma non sulle variabili della tabella.Sebbene le modifiche dello schema siano possibili su tabelle temporanee, evitare di usarle perché causano ricompilazioni di dichiarazioni che utilizzano le tabelle.

Temporary Tables versus Table Variables

LE VARIABILI DELLA TABELLA NON VENGONO CREATE IN MEMORIA

C'è un malinteso comune che le variabili della tabella siano strutture in memoria e come tali funzionano più rapidamente delle tabelle temporanee.Grazie a un DMV chiamato sys.dm _ db _ sessione _ spazio _ utilizzo, che mostra l'utilizzo di tempdb per sessione, puoi dimostrare che non è così.Dopo aver riavviato SQL Server per cancellare il DMV, eseguire il seguente script per configurare che la sessione _ ID restituisce 0 per l'utente _ Oggetti _ Alloc _ Pagina _ Contare

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

Ora puoi controllare quanto spazio utilizza una tabella temporanea eseguendo il seguente script per creare una tabella temporanea con una colonna e popolarla con una riga:

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 ;

I risultati sul mio server indicano che alla tabella è stata allocata una pagina in tempdb.Ora esegui lo stesso script ma usa una variabile tabella questa volta:

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 ;

Quale usare?

Se si utilizzano o meno tabelle temporanee o variabili della tabella devono essere decisi da test approfonditi, ma è meglio propendere per il temporaneo tabelle come predefinite perché ci sono molte meno cose che possono andare sbagliato.

Ho visto i clienti sviluppare il codice utilizzando le variabili della tabella perché avevano a che fare con una piccola quantità di righe, ed era più veloce di una tabella temporanea, ma qualche anno dopo c'erano centinaia di migliaia di righe nella variabile della tabella e le prestazioni erano terribili , quindi prova a consentire una pianificazione delle capacità quando prendi la tua decisione!

Un'altra differenza:

È possibile accedere a una variabile di tabella solo dalle istruzioni all'interno della procedura che la crea, non da altre procedure chiamate da tale procedura o da SQL dinamico annidato (tramite exec o sp_executesql).

L'ambito di una tabella temporanea, invece, include il codice nelle procedure chiamate e nell'SQL dinamico annidato.

Se la tabella creata dalla procedura deve essere accessibile da altre procedure richiamate o da SQL dinamico, è necessario utilizzare una tabella temporanea.Questo può essere molto utile in situazioni complesse.

Considera anche che spesso puoi sostituire entrambi con tabelle derivate che potrebbero essere anche più veloci.Come per tutte le ottimizzazioni delle prestazioni, tuttavia, solo i test effettivi rispetto ai dati effettivi possono dirti l'approccio migliore per la tua query particolare.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top