it-swarm-eu.dev

Jaký je rozdíl mezi CTE a Temp Table?

Jaký je rozdíl mezi výrazem Common Table Expression (CTE) a dočasnou tabulkou? A kdy bych měl použít jeden nad druhým?

CTE

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

SELECT * FROM cte

Temp Table

SELECT Column1, Column2, Column3
INTO #tmpTable
FROM SomeTable

SELECT * FROM #tmpTable
179
Rachel

To je docela široké, ale dám vám tak obecnou odpověď, jak umím.

CTE ...

  • Jsou neindexovatelné (ale mohou používat existující indexy na odkazovaných objektech)
  • Nelze mít omezení
  • Jsou v podstatě jednorázové VIEWs
  • Přetrvávat pouze do spuštění dalšího dotazu
  • Může být rekurzivní
  • Nemáte vyhrazené statistiky (spoléhejte se na statistiky podkladových objektů)

# Temp Tables ...

  • Jsou skutečné materializované tabulky, které existují v tempdb
  • Lze indexovat
  • Může mít omezení
  • Přetrvávají po celý život současného PŘIPOJENÍ
  • Lze na ni odkazovat pomocí jiných dotazů nebo podprogramů
  • Mají vyhrazené statistiky generované motorem

Pokud jde o to, kdy použít každý, mají velmi odlišné případy použití. Pokud budete mít velmi velký soubor výsledků nebo potřebujete-li na něj odkazovat vícekrát, vložte jej do #temp stůl. Pokud musí být rekurzivní, jednorázové nebo jen logicky zjednodušit, dává se přednost CTE.

Také CTE by mělo nikdy se nepoužívá pro výkon. Téměř nikdy nebudete urychlovat pomocí CTE, protože opět je to jen pohled na jedno použití. Můžete s nimi dělat nějaké úhledné věci, ale urychlení dotazu ve skutečnosti není jedna z nich.

204
JNK

ÚPRAVA:

Viz Martinovy ​​komentáře níže:

CTE není zhmotněn jako tabulka v paměti. Je to jen způsob, jak zapouzdřit definici dotazu. V případě OP to bude vloženo a stejné jako při provádění SELECT Column1, Column2, Column3 FROM SomeTable. Většinu času se nenaplňují dopředu, a proto se vrací žádné řádky WITH T(X) AS (SELECT NEWID())SELECT * FROM T T1 JOIN T T2 ON T1.X=T2.X, také zkontrolujte prováděcí plány. I když někdy je možné hacknout plán dostat cívku. Existuje položka připojení vyžadující nápovědu. - Martin Smith 15. února v 17:08


Původní odpověď

CTE

Přečtěte si více v MSDN

CTE vytvoří tabulku používanou v paměti, ale je platná pouze pro konkrétní dotaz následující. Při použití rekurze to může být efektivní struktura.

Můžete také zvážit použití proměnné tabulky. Používá se jako používá se dočasná tabulka a lze ji použít vícekrát, aniž byste museli být znovu materializováni pro každé spojení. Také, pokud potřebujete přetrvávat několik záznamů nyní, přidejte několik dalších záznamů po dalším výběru, přidejte několik dalších záznamů po dalším operaci, pak vraťte jen ty hrstky záznamů, pak to může být užitečná struktura, protože nemá Po provedení nemusí být upuštěno. Většinou jen syntaktický cukr. Pokud však udržujete počet řádků nízký, nikdy se nenaplní na disk. Další podrobnosti viz Jaký je rozdíl mezi dočasnou tabulkou a proměnnou tabulky v SQL Server? .

Tabulka teplot

Přečtěte si více v MSDN - Přejděte dolů asi 40% cesty

Časová tabulka je doslova tabulka vytvořená na disku, pouze v konkrétní databázi, kterou může každý smazat. Je dobrým vývojářem zničit tyto tabulky, když již nejsou potřeba, ale DBA je může také vymazat.

Dočasné tabulky jsou nabízeny ve dvou variantách: místní a globální. Pokud jde o server MS Sql, používáte pro místní označení #tableName A pro globální označení ##tableName (Jako identifikační charakteristiku použijte jedno nebo dvojité číslo #).

Všimněte si, že u dočasných tabulek, na rozdíl od proměnných tabulky nebo CTE, můžete použít indexy a podobně, protože se jedná o legitimní tabulky v normálním slova smyslu.


Obecně bych používal dočasné tabulky pro delší nebo větší dotazy a CTE nebo proměnné tabulky, kdybych už měl malý dataset a chtěl bych jen rychle skriptovat trochu kódu pro něco malého. Zkušenosti a rady ostatních naznačují, že byste měli používat CTE tam, kde se z nich vrací malý počet řádků. Pokud máte velké číslo, pravděpodobně byste měli prospěch z indexování v dočasné tabulce.

29
jcolebrand

přijatá odpověď zde říká: „CTE by nikdy neměl být použit pro výkon“ - ale to by mohlo být zavádějící. V souvislosti s tabulkami CTE versus temp jsem právě dokončil odstranění shluku nevyžádaných souborů ze sady uložených proců, protože někteří doofové si museli myslet, že použití dočasných tabulek bylo malé nebo žádné. Hodil jsem to do CTE, , s výjimkou těch, které byly legitimně znovu použity během celého procesu. Získal jsem asi 20% výkon všech metrik. Poté jsem začal odstraňovat všechny kurzory, které se snažily implementovat rekurzivní zpracování. Tam jsem viděl největší zisk. Nakonec jsem zkrátil dobu odezvy desetkrát.

CTE a temp tabulky mají velmi odlišné případy použití. Chci jen zdůraznit, že i když nejde o všelék, porozumění a správné použití CTE může vést k některým skutečně hvězdným zlepšením jak kvality/udržovatelnosti kódu, tak rychlosti. Od té doby, co jsem na ně narazil, vidím dočasné tabulky a kurzory jako velké zlo zpracování SQL. S tabulkovými proměnnými a CTE mohu být v pohodě téměř teď. Můj kód je čistší a rychlejší.

17
Mel Padden

CTE může být vyvolán opakovaně v dotazu a je vyhodnocen pokaždé, když se na něj odkazuje - tento proces může být rekurzivní. Pokud je to jen jednou odkázáno, chová se podobně jako dílčí dotaz, ačkoli CTE lze parametrizovat.

Dočasná tabulka fyzicky přetrvává a může být indexována. V praxi může optimalizátor dotazů také přetrvávat mezilehlé výsledky spojování nebo dílčího dotazu v zákulisí, jako jsou operace zařazování, takže není zcela pravda, že výsledky CTE nikdy na disk nepřetrvávají.

Proměnné tabulky IIRC (na druhé straně) jsou vždy struktury v paměti.

Tabulka temp je skutečným objektem v databázi tempdb, ale cte je pouze druh obalu kolem složeného dotazu, který zjednodušuje syntaxi rekurze organizování v jednom kroku.

11
Oleg Dok

Primárním důvodem pro použití CTE je přístup k funkcím Window, jako je row_number() a různé další.

To znamená, že můžete dělat věci jako získat první nebo poslední řádek ve skupině VELMI VELMI rychle a efektivně - ve většině praktických případů účinněji než jiné prostředky .

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

Podobný dotaz jako výše můžete spustit pomocí korelovaného poddotazu nebo pomocí dotazu, ale CTE bude rychlejší ve všech scénářích.

Kromě toho mohou CTE opravdu pomoci zjednodušit váš kód. To může vést ke zvýšení výkonu, protože lépe porozumíte dotazu a můžete zavést více obchodní logiky, aby optimalizátor mohl být selektivnější.

Kromě toho mohou CTE zvýšit výkon, pokud rozumíte své obchodní logice a víte, které části dotazu by měly být spuštěny jako první - obvykle nejprve dejte nejelektivnější dotazy, které vedou k sadám výsledků, které mohou použít index při jejich příštím připojení, a přidejte option(force order) nápověda pro dotaz

Konečně CTE ve výchozím nastavení nepoužívají tempdb, takže omezením tvrzení omezíte jejich používání.

Dočasné tabulky by měly být použity, pokud potřebujete data dotazovat vícekrát, nebo alternativně, pokud změříte vaše dotazy a zjistíte, že vložením do dočasné tabulky a pak přidáte index, který zlepšuje váš výkon.

8
Dave Hilditch

Zdá se, že je zde trochu negativity vůči CTE.

Moje chápání CTE je, že je to v podstatě druh adhoc pohledu. SQL je deklarativní i množinový jazyk. CTE jsou skvělý způsob, jak deklarovat soubor! Neschopnost indexovat CTE je ve skutečnosti dobrá věc, protože nemusíte! Je to opravdu druh syntaktického cukru, který usnadňuje čtení/zápis. Každý slušný optimalizátor vypracuje nejlepší přístupový plán pomocí indexů v podkladových tabulkách. To znamená, že byste mohli efektivně urychlit svůj dotaz CTE sledováním rady s indexem v podkladových tabulkách.

Také proto, že jste definovali množinu jako CTE, neznamená to, že musí být zpracovány všechny řádky v sadě. V závislosti na dotazu může optimalizátor zpracovat řádky „jen dost“, aby vyhověl dotazu. Možná jste potřebovali pouze prvních asi 20 pro vaši obrazovku. Pokud jste vytvořili dočasnou tabulku, musíte opravdu všechny tyto řádky číst/zapisovat!

Na základě toho bych řekl, že CTE jsou skvělou vlastností SQL a lze je použít kdekoli, aby usnadnili čtení dotazu. Přemýšlel jsem jen o dočasné tabulce pro dávkový proces, který by skutečně musel zpracovat každý jednotlivý záznam. I v tom případě to není opravdu doporučeno, protože v dočasné tabulce je pro databázi mnohem těžší pomoci s ukládáním do mezipaměti a indexy. Může být lepší mít permanentní tabulku s polem PK jedinečným pro vaši transakci.

Musím přiznat, že moje zkušenost je hlavně s DB2, takže předpokládám, že práce CTE podobným způsobem v obou produktech. Naštěstí budu opraven, pokud jsou CTE nějak podřadné na serveru SQL. ;)

6
Ben Thurley