Database
 sql >> Database >  >> RDS >> Database

Miti sulle prestazioni:le variabili della tabella sono sempre in memoria

Autore ospite:Derik Hammer (@SQLHammer)


Di recente Aaron Bertrand ha pubblicato un blog sui miti dannosi e pervasivi sulle prestazioni di SQL Server. Come estensione di questa serie di blog, smentirò questo mito comune:

"Le variabili di tabella sono sempre in memoria, quindi più veloci delle tabelle temporanee."

Lettura del manuale

Andando direttamente alla fonte, ho esaminato l'articolo della documentazione in linea sulle tabelle che include variabili di tabella. Anche se l'articolo fa riferimento ai vantaggi dell'utilizzo delle variabili di tabella, il fatto che siano al 100% in memoria è evidentemente assente.

Tuttavia, un affermativo mancante non implica un negativo. Dal momento che le tabelle OLTP in memoria sono state rilasciate, ora c'è molta più documentazione in BOL per l'elaborazione in memoria. È qui che ho trovato questo articolo su come rendere più veloci tabelle temporanee e variabili di tabella utilizzando l'ottimizzazione della memoria.

L'intero articolo ruota attorno a come fare in modo che i tuoi oggetti temporanei utilizzino la funzione OLTP in memoria, ed è qui che ho trovato l'affermazione che stavo cercando.

"Una variabile di tabella tradizionale rappresenta una tabella nel database tempdb. Per prestazioni molto più veloci è possibile ottimizzare la memoria della variabile di tabella."

Le variabili di tabella non sono costrutti in memoria. Per utilizzare la tecnologia in-memory devi definire in modo esplicito un TYPE che sia ottimizzato per la memoria e utilizzare quel TYPE per definire la tua variabile di tabella.

Dimostralo

La documentazione è una cosa, ma vederla con i miei occhi è un'altra. So che le tabelle temporanee creano oggetti in tempdb e scriveranno i dati su disco. Per prima cosa ti mostrerò come appare per le tabelle temporanee e poi userò lo stesso metodo per convalidare l'ipotesi che le variabili di tabella agiscano allo stesso modo.

Analisi dei record di registro

Questa query eseguirà un CHECKPOINT per darmi un punto di partenza pulito e quindi mostrerà il numero di record di registro e i nomi delle transazioni che esistono nel registro.

USE tempdb;
GO
 
CHECKPOINT;
GO
 
SELECT COUNT(*) [Count] 
  FROM sys.fn_dblog (NULL, NULL);
 
SELECT [Transaction Name]
  FROM sys.fn_dblog (NULL, NULL)
  WHERE [Transaction Name] IS NOT NULL;


L'esecuzione ripetuta di T-SQL ha comportato un conteggio coerente di tre record su SQL Server 2016 SP1.

In questo modo viene creata una tabella temporanea e viene visualizzato il record dell'oggetto, dimostrando che si tratta di un oggetto reale in tempdb.

USE tempdb;
GO
 
DROP TABLE IF EXISTS #tmp;
GO
 
CREATE TABLE #tmp (id int NULL);
 
SELECT name
  FROM sys.objects o
  WHERE is_ms_shipped = 0;

Ora mostrerò di nuovo i record di registro. Non eseguirò nuovamente il comando CHECKPOINT.

Sono stati scritti ventuno record di registro, a dimostrazione del fatto che si tratta di scritture su disco e il nostro CREATE TABLE è chiaramente incluso in questi record di registro.

Per confrontare questi risultati con le variabili di tabella, ripristinerò l'esperimento eseguendo CHECKPOINT e quindi eseguendo il seguente T-SQL, creando una variabile di tabella.

USE tempdb;
GO
 
DECLARE @var TABLE (id int NULL);
 
SELECT name
  FROM sys.objects o
  WHERE is_ms_shipped = 0;

Ancora una volta abbiamo un nuovo record di oggetti. Questa volta, tuttavia, il nome è più casuale rispetto alle tabelle temporanee.

Ci sono ottantadue nuovi record di registro e nomi di transazione che dimostrano che la mia variabile viene scritta nel registro e, quindi, sul disco.

Realmente in memoria

Ora è il momento per me di far scomparire i record di registro.

Ho creato un filegroup OLTP in memoria e quindi ho creato un tipo di tabella ottimizzato per la memoria.

USE Test;
GO
 
CREATE TYPE dbo.inMemoryTableType  
  AS TABLE 
  ( id INT NULL INDEX ix1 )
  WITH (MEMORY_OPTIMIZED = ON);  
GO

Ho eseguito nuovamente il CHECKPOINT e quindi ho creato la tabella ottimizzata per la memoria.

USE Test;
GO
 
DECLARE @var dbo.inMemoryTableType;
 
INSERT INTO @var (id) VALUES (1)
 
SELECT * from @var;  
GO

Dopo aver esaminato il registro, non ho visto alcuna attività del registro. Questo metodo è infatti al 100% in memoria.

Porta via

Le variabili di tabella utilizzano tempdb in modo simile a come utilizzano tempdb le tabelle temporanee. Le variabili di tabella non sono costrutti in memoria, ma possono diventarle se si utilizzano tipi di tabella definiti dall'utente ottimizzati per la memoria. Spesso trovo che le tabelle temporanee siano una scelta molto migliore rispetto alle variabili di tabella. Il motivo principale è perché le variabili di tabella non hanno statistiche e, a seconda della versione e delle impostazioni di SQL Server, le stime di riga risultano essere 1 riga o 100 righe. In entrambi i casi si tratta di supposizioni e diventano dannose informazioni errate nel processo di ottimizzazione delle query.

Si noti che alcune di queste differenze di funzionalità possono cambiare nel tempo, ad esempio, nelle versioni recenti di SQL Server è possibile creare indici aggiuntivi su una variabile di tabella usando la sintassi dell'indice inline. La tabella seguente ha tre indici; la chiave primaria (in cluster per impostazione predefinita) e due indici non in cluster:

DECLARE @t TABLE
(
  a int PRIMARY KEY,
  b int,
  INDEX x (b, a DESC),
  INDEX y (b DESC, a)
);

C'è un'ottima risposta su DBA Stack Exchange in cui Martin Smith descrive in modo esauriente le differenze tra le variabili di tabella e le tabelle #temp:

  • Qual ​​è la differenza tra una tabella temporanea e una variabile di tabella in SQL Server?

Informazioni sull'autore

Derik è un professionista dei dati e un MVP Microsoft Data Platform appena coniato incentrato su SQL Server. La sua passione si concentra sull'elevata disponibilità, sul ripristino di emergenza, sull'integrazione continua e sulla manutenzione automatizzata. La sua esperienza ha abbracciato l'amministrazione di database a lungo termine, la consulenza e le iniziative imprenditoriali che lavorano nei settori finanziario e sanitario. Attualmente è un Senior Database Administrator responsabile del team Database Operations presso Subway Franchise World Headquarters. Quando non è in orario o non sta scrivendo su SQLHammer.com, Derik dedica il suo tempo alla famiglia #sql come Chapter Leader per il gruppo di utenti di FairfieldPASS SQL Server a Stamford, CT.