it-swarm.it

Qual è la differenza tra una tabella CTE e una tabella temporanea?

Qual è la differenza tra una Common Table Expression (CTE) e una tabella temporanea? E quando dovrei usarne uno sopra l'altro?

[~ ~ #] CTE [~ ~ #]

WITH cte (Column1, Column2, Column3)
AS
(
    SELECT Column1, Column2, Column3
    FROM SomeTable
)

SELECT * FROM cte

Tabella temp

SELECT Column1, Column2, Column3
INTO #tmpTable
FROM SomeTable

SELECT * FROM #tmpTable
179
Rachel

È piuttosto ampio, ma ti darò una risposta il più generale possibile.

CTE ...

  • Non indicizzabili (ma possono utilizzare indici esistenti su oggetti referenziati)
  • Non possono avere vincoli
  • Sono essenzialmente usa e getta VIEWs
  • Persiste solo fino all'esecuzione della query successiva
  • Può essere ricorsivo
  • Non hai statistiche dedicate (fai affidamento sulle statistiche sugli oggetti sottostanti)

# Tabelle temporanee ...

  • Sono vere tabelle materializzate che esistono in tempdb
  • Può essere indicizzato
  • Può avere vincoli
  • Persistere per la vita dell'attuale CONNESSIONE
  • Può essere referenziato da altre query o sottoprocedure
  • Hanno statistiche dedicate generate dal motore

Per quanto riguarda quando utilizzarli, hanno casi d'uso molto diversi. Se hai un set di risultati molto grande o devi fare riferimento ad esso più di una volta, inseriscilo in un #temp tavolo. Se deve essere ricorsivo, è usa e getta o è solo per semplificare qualcosa logicamente, è preferibile un CTE.

Inoltre, un CTE dovrebbe mai usato per le prestazioni. Non accelererai quasi mai le cose usando un CTE, perché, di nuovo, è solo una vista usa e getta. Puoi fare alcune cose pulite con loro, ma accelerare una query non è davvero uno di questi.

204
JNK

EDIT:

Si prega di vedere i commenti di Martin di seguito:

Il CTE non si materializza come una tabella in memoria. È solo un modo per incapsulare una definizione di query. Nel caso dell'OP sarà integrato e lo stesso che fare semplicemente SELECT Column1, Column2, Column3 FROM SomeTable. Il più delle volte non si materializzano in anticipo, motivo per cui questo non restituisce righe WITH T(X) AS (SELECT NEWID())SELECT * FROM T T1 JOIN T T2 ON T1.X=T2.X, controlla anche i piani di esecuzione. Anche se a volte è possibile hackerare il piano per ottenere una bobina. C'è un elemento di connessione che richiede un suggerimento per questo. - Martin Smith, 15 febbraio 12 alle 17:08


Risposta originale

CTE

Leggi di più su MSDN

Un CTE crea la tabella utilizzata in memoria, ma è valida solo per la query specifica che la segue. Quando si utilizza la ricorsione, questa può essere una struttura efficace.

Potresti anche prendere in considerazione l'utilizzo di una variabile di tabella. Viene utilizzato as viene utilizzata una tabella temporanea che può essere utilizzata più volte senza necessità di essere nuovamente materializzata per ogni join. Inoltre, se è necessario persistere alcuni record ora, aggiungere alcuni altri record dopo la selezione successiva, aggiungere alcuni altri record dopo un'altra operazione, quindi restituire solo quei pochi record, quindi questa può essere una struttura pratica, come non non è necessario lasciarlo cadere dopo l'esecuzione. Principalmente solo zucchero sintattico. Tuttavia, se si mantiene basso il conteggio delle righe, non si materializza mai su disco. Vedere Qual è la differenza tra una tabella temporanea e una variabile di tabella in SQL Server? per maggiori dettagli.

Tabella temporanea

Leggi di più su MSDN - Scorri verso il basso di circa il 40%

Una tabella temporanea è letteralmente una tabella creata su disco, solo in un database specifico che tutti sanno che può essere eliminato. È responsabilità di un buon sviluppatore distruggere quei tavoli quando non sono più necessari, ma un DBA può anche cancellarli.

Le tabelle temporanee sono disponibili in due varietà: locale e globale. In termini di MS Sql Server si utilizza una designazione #tableName Per locale e ##tableName Per globale (notare l'uso di un singolo o doppio # come caratteristica identificativa).

Si noti che con le tabelle temporanee, al contrario delle variabili di tabella o CTE, è possibile applicare indici e simili, poiché si tratta legittimamente di tabelle nel senso normale della Parola.


Generalmente userei le tabelle temporanee per query più lunghe o più grandi, e CTE o variabili di tabella se avessi già un piccolo set di dati e volessi semplicemente scrivere un po 'di codice per qualcosa di piccolo. L'esperienza e i consigli di altri indicano che è necessario utilizzare CTE laddove si riceva un numero limitato di righe. Se hai un numero elevato, probabilmente trarrai vantaggio dalla possibilità di indicizzare sulla tabella temporanea.

29
jcolebrand

Il risposta accettata qui dice "un CTE non dovrebbe mai essere usato per le prestazioni" - ma ciò potrebbe fuorviare. Nel contesto dei CTE rispetto alle tabelle temporanee, ho appena finito di rimuovere una serie di spazzatura da una suite di processi archiviati perché alcuni doofus devono aver pensato che ci fosse poco o nessun sovraccarico nell'uso delle tabelle temporanee. Ho inserito il lotto in CTE, tranne quelli che sarebbero stati legittimamente riutilizzati durante tutto il processo. Ho ottenuto circa il 20% di prestazioni da tutte le metriche. Ho quindi iniziato a rimuovere tutti i cursori che stavano cercando di implementare l'elaborazione ricorsiva. Questo è dove ho visto il massimo guadagno. Ho finito per ridurre i tempi di risposta di un fattore dieci.

I CTE e le tabelle temporanee hanno casi d'uso molto diversi. Voglio solo sottolineare che, sebbene non sia una panacea, la comprensione e l'uso corretto dei CTE possono portare ad alcuni miglioramenti davvero stellari sia nella qualità/manutenibilità del codice che nella velocità. Da quando li ho presi, vedo le tabelle temporanee e i cursori come i grandi mali dell'elaborazione SQL. Ora riesco a cavarmela bene con variabili di tabella e CTE per quasi tutto. Il mio codice è più pulito e veloce.

17
Mel Padden

Un CTE può essere chiamato ripetutamente all'interno di una query e viene valutato ogni volta che viene referenziato: questo processo può essere ricorsivo. Se viene fatto riferimento una sola volta, si comporta in modo molto simile a una query secondaria, sebbene i CTE possano essere parametrizzati.

Una tabella temporanea è fisicamente persistente e può essere indicizzata. In pratica, Query Optimizer può anche persistere risultati intermedi di join o query secondarie dietro le quinte, come nelle operazioni di spooling, quindi non è strettamente vero che i risultati dei CTE non vengono mai mantenuti sul disco.

Le variabili della tabella IIRC (d'altra parte) sono sempre strutture in memoria.

La tabella temporanea è un oggetto reale in tempdb, ma cte è solo un tipo di wrapper attorno a query complesse per semplificare la sintassi dell'organizzazione della ricorsione in un solo passaggio.

11
Oleg Dok

Il motivo principale per utilizzare CTE è accedere alle funzioni della finestra come row_number() e vari altri.

Ciò significa che puoi fare cose come ottenere la prima o l'ultima riga per gruppo MOLTO MOLTO in modo rapido ed efficiente - più efficiente di altri mezzi nella maggior parte dei casi pratici .

with reallyfastcte as (
select *, 
row_number() over (partition by groupingcolumn order by sortingcolumn) as rownum
from sometable
)
select *
from reallyfastcte
where rownum = 1;

È possibile eseguire una query simile alla precedente utilizzando una query secondaria correlata o utilizzando una query secondaria ma il CTE sarà più veloce in quasi tutti gli scenari.

Inoltre, i CTE possono davvero aiutarti a semplificare il tuo codice. Questo può portare a miglioramenti delle prestazioni perché comprendi di più la query e puoi introdurre più logica di business per aiutare l'ottimizzatore a essere più selettivo.

Inoltre, i CTE possono migliorare le prestazioni se capisci la tua logica aziendale e sai quali parti della query devono essere eseguite per prime, in genere metti le tue query più selettive al primo posto che portano a set di risultati che possono usare un indice nel loro prossimo join e aggiungi il option(force order) suggerimento query

Infine, i CTE non usano tempdb per impostazione predefinita, quindi riduci la contesa su quel collo di bottiglia attraverso il loro uso.

Le tabelle temporanee devono essere utilizzate se è necessario eseguire query sui dati più volte o, in alternativa, se si misurano le query e si scopre inserendo in una tabella temporanea e quindi aggiungendo un indice per migliorare le prestazioni.

8
Dave Hilditch

Sembra esserci un po 'di negatività qui nei confronti di CTE.

La mia comprensione di un CTE è che è fondamentalmente una specie di visione ad hoc. SQL è un linguaggio sia dichiarativo che basato su set. I CTE sono un ottimo modo per dichiarare un set! Non essere in grado di indicizzare un CTE è in realtà una buona cosa perché non è necessario! È davvero una specie di zucchero sintattico per facilitare la lettura/scrittura della query. Qualsiasi ottimizzatore decente elaborerà il miglior piano di accesso utilizzando gli indici nelle tabelle sottostanti. Ciò significa che è possibile velocizzare efficacemente la query CTE seguendo i consigli sull'indice nelle tabelle sottostanti.

Inoltre, solo perché hai definito un set come CTE, ciò non significa che tutte le righe nel set debbano essere elaborate. A seconda della query, l'ottimizzatore potrebbe elaborare righe "appena sufficienti" per soddisfare la query. Forse hai solo bisogno dei primi 20 circa per il tuo schermo. Se hai creato una tabella temporanea, devi davvero leggere/scrivere tutte quelle righe!

Sulla base di questo direi che i CTE sono una grande funzionalità di SQL e possono essere utilizzati ovunque rendano più semplice la lettura della query. Vorrei solo pensare a una tabella temporanea per un processo batch che avrebbe davvero bisogno di elaborare ogni singolo record. Anche allora afaik non è davvero raccomandato perché su una tabella temporanea è molto più difficile per il database aiutarti con la cache e gli indici. Potrebbe essere meglio avere una tabella permanente con un campo PK univoco per la tua transazione.

Devo ammettere che la mia esperienza è principalmente con DB2, quindi presumo che il lavoro di CTE sia simile in entrambi i prodotti. Sarò felicemente corretto se i CTE sono in qualche modo inferiori nel server SQL. ;)

6
Ben Thurley