INSERISCI differenza di prestazioni tra tabelle temporanee e variabili di tabella


12

Ho il seguente problema in SQL Server 2005: il tentativo di inserire alcune righe in una variabile di tabella richiede molto tempo rispetto allo stesso inserimento mediante una tabella temporanea.

Questo è il codice da inserire nella variabile della tabella

DECLARE @Data TABLE(...)
INSERT INTO @DATA( ... )
SELECT ..
FROM ...

Questo è il codice da inserire nella tabella temporanea

CREATE #Data TABLE(...)
INSERT INTO #DATA( ... )
SELECT ..
FROM ...
DROP TABLE #Data

La tabella temporanea non ha chiavi o indici, la parte selezionata è la stessa tra le 2 query e il numero di risultati restituiti dalla selezione è ~ 10000 righe. Il tempo necessario per eseguire la selezione da solo è di ~ 10 secondi.

La versione della tabella temporanea impiega fino a 10 secondi per essere eseguita, ho dovuto interrompere la versione variabile della tabella dopo 5 minuti.

Devo usare una variabile di tabella perché la query fa parte di una funzione di valore di tabella, che non consente l'accesso alla tabella temporanea.

Piano di esecuzione per la versione variabile della tabella Progetto esecutivo

Piano di esecuzione per la versione della tabella temporanea Progetto esecutivo

Risposte:


8

L'ovvia differenza tra i due piani è che quello veloce è parallelo e quello più lento seriale.

Questa è una delle limitazioni dei piani che si inseriscono nelle variabili di tabella. Come menzionato nei commenti (e sembra che abbia avuto l'effetto desiderato) potresti provare a farlo

INSERT INTO @DATA ( ... ) 
EXEC('SELECT .. FROM ...')

per vedere se questo aggira la limitazione.


È stato un ottimo suggerimento, anche se ho pensato che non si potesse usare EXECuna funzione .... Immagino di essermi sbagliato
Lamak,

1
@Lamak - Doh! Non puoi, quindi non funzionerà per l'OP. Invalid use of a side-effecting operator 'INSERT EXEC' within a function.. Il OPENQUERYlavoro potrebbe comunque funzionare.
Martin Smith,

Ah, buono a sapersi, grazie per il chiarimento
Lamak,

2
Come regola generale, non si desidera utilizzare le variabili di tabella se si prevede di restituire un set di dati di grandi dimensioni. Le tabelle temporanee sono generalmente più veloci in questo caso.
HLGEM,

1
@munissor, quindi non utilizzare una funzione con valori di tabella. Se vuoi un consiglio migliore, pubblica esattamente quello che stai facendo.
HLGEM,

-1

Le variabili di tabella a volte sono più lente perché non ci sono statistiche sulle variabili di tabella e quindi l'ottimizzatore assume sempre un solo record.

Tuttavia, non posso garantire che questo sia il caso qui, dovrete dare un'occhiata alle informazioni sulle "righe stimate" nel piano di query per la variabile della tabella.


In che modo ciò influirebbe su un inserimento in una variabile di tabella?
Martin Smith,

Questo è ciò che sembra stia succedendo, poiché puoi vedere che non c'è solo una differenza tra parallelo e seriale ma anche tra join hash e loop nidificati, a quanto pare l'ottimizzatore presuppone che, poiché la variabile della tabella contiene un record nella sua mente, il risultato della query sarà anche un record, ancora una volta l'unico modo per dimostrare che sarebbe vedere le statistiche effettive per ogni parte della query, ma il fatto è che tutte le query che coinvolgono variabili di tabella finiscono con join di loop ed elaborazione seriale, quindi penso che sia giusto sospettarlo qui
giocherete il
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.