sql >> Databáze >  >> RDS >> Sqlserver

Které jsou výkonnější, CTE nebo dočasné tabulky?

To záleží.

Za prvé

Co je běžný tabulkový výraz?

S (nerekurzivním) CTE se zachází velmi podobně jako s jinými konstrukcemi, které lze také použít jako výrazy vložené tabulky na serveru SQL Server. Odvozené tabulky, pohledy a funkce s hodnotou vložené tabulky. Všimněte si, že zatímco BOL říká, že CTE „lze považovat za dočasnou sadu výsledků“, jde o čistě logický popis. Častěji není zhmotněna sama o sobě.

Co je to dočasná tabulka?

Toto je kolekce řádků uložených na datových stránkách v databázi tempdb. Datové stránky mohou být částečně nebo zcela uloženy v paměti. Dočasná tabulka může být navíc indexována a může mít statistiku sloupců.

Testovací data

CREATE TABLE T(A INT IDENTITY PRIMARY KEY, B INT , F CHAR(8000) NULL);

INSERT INTO T(B)
SELECT TOP (1000000)  0 + CAST(NEWID() AS BINARY(4))
FROM master..spt_values v1,
     master..spt_values v2;

Příklad 1

WITH CTE1 AS
(
SELECT A,
       ABS(B) AS Abs_B,
       F
FROM T
)
SELECT *
FROM CTE1
WHERE A = 780

Upozornění ve výše uvedeném plánu není žádná zmínka o CTE1. Pouze přistupuje přímo k základním tabulkám a je s ním zacházeno stejně jako

SELECT A,
       ABS(B) AS Abs_B,
       F
FROM   T
WHERE  A = 780 

Přepsání zhmotněním CTE do přechodné dočasné tabulky by bylo značně kontraproduktivní.

Zhmotnění definice CTE pro

SELECT A,
       ABS(B) AS Abs_B,
       F
FROM T

Zahrnovalo by to zkopírování asi 8 GB dat do dočasné tabulky, pak je tu také režie na výběr z ní.

Příklad 2

WITH CTE2
     AS (SELECT *,
                ROW_NUMBER() OVER (ORDER BY A) AS RN
         FROM   T
         WHERE  B % 100000 = 0)
SELECT *
FROM   CTE2 T1
       CROSS APPLY (SELECT TOP (1) *
                    FROM   CTE2 T2
                    WHERE  T2.A > T1.A
                    ORDER  BY T2.A) CA 

Výše uvedený příklad trvá na mém počítači asi 4 minuty.

Pouze 15 řádků z 1 000 000 náhodně vygenerovaných hodnot odpovídá predikátu, ale drahé prohledání tabulky proběhne 16krát, aby je bylo možné najít.

To by byl dobrý kandidát pro zhmotnění průběžného výsledku. Přepsání ekvivalentní dočasné tabulky trvalo 25 sekund.

INSERT INTO #T
SELECT *,
       ROW_NUMBER() OVER (ORDER BY A) AS RN
FROM   T
WHERE  B % 100000 = 0

SELECT *
FROM   #T T1
       CROSS APPLY (SELECT TOP (1) *
                    FROM   #T T2
                    WHERE  T2.A > T1.A
                    ORDER  BY T2.A) CA 

Průběžná materializace části dotazu do dočasné tabulky může být někdy užitečná, i když je vyhodnocena pouze jednou – když umožňuje rekompilaci zbytku dotazu s využitím statistik o materializovaném výsledku. Příklad tohoto přístupu je v článku SQL Cat When To Break Down Complex Queries.

Za určitých okolností SQL Server použije zařazování do mezipaměti mezivýsledků, např. CTE a vyhnout se nutnosti přehodnocování tohoto podstromu. To je diskutováno v položce (migrované) Connect Poskytnout nápovědu k vynucení přechodné materializace CTE nebo odvozených tabulek. Nejsou však o tom vytvářeny žádné statistiky, a i kdyby se počet řádků pro souběžný tisk měl výrazně lišit od odhadovaného, ​​není možné, aby se probíhající plán provádění dynamicky přizpůsoboval v reakci (alespoň v aktuálních verzích. Adaptivní plány dotazů mohou být možné v budoucnost).



  1. Jak získat BLOB ze souboru v PL/SQL?

  2. Nejnovější trendy PostgreSQL:Nejvíce časově náročné úkoly a důležité metriky ke sledování

  3. Rozdělení řetězce na serveru SQL

  4. Nyní můžete používat Access s Microsoft Azure MFA!