Które są bardziej wydajne, CTE lub tymczasowe tabele?

Które są bardziej wydajne, CTE Czy Temporary Tables?

Author: DineshDB, 2009-03-27

12 answers

Powiedziałbym, że są to różne pojęcia, ale nie zbyt różne, aby powiedzieć "kreda i ser".

  • Tabela tymczasowa jest dobra do ponownego użycia lub do wykonywania wielu przejść przetwarzania na zestawie danych.

  • CTE może być używany do rekurencji lub po prostu do poprawy czytelności.
    Podobnie jak widok lub funkcja wartościowana w tabeli liniowej może być również traktowana jak makro, które ma zostać rozszerzone w głównym zapytaniu

  • Tabela tymczasowa to kolejna tabela z pewnymi zasadami wokół zakres

Mam zapisane procs gdzie używam both (i Table variables too)

 64
Author: gbn,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-07-13 11:18:44

To zależy.

Po pierwsze

Co to jest Common table Expression?

A (non recursive) CTE jest traktowany bardzo podobnie do innych konstrukcji, które mogą być również używane jako wyrażenia tabeli inline w SQL Server. Pochodne tabele, widoki i funkcje wartościowane w tabeli inline. Zauważ, że chociaż BOL mówi, że CTE "może być traktowany jako tymczasowy zestaw wyników" , jest to czysto logiczny opis. Częściej niż nie jest materlializowana we własnym racja.

Czym jest stół tymczasowy?

Jest to zbiór wierszy przechowywanych na stronach danych w programie tempdb. Strony danych mogą znajdować się częściowo lub w całości w pamięci. Dodatkowo tymczasowa tabela może być indeksowana i posiadać statystyki kolumnowe.

Dane Testowe

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;

Przykład 1

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

Plan 1

Uwaga w powyższym planie nie ma wzmianki o CTE1. Po prostu uzyskuje bezpośredni dostęp do tabel podstawowych i jest traktowany tak samo as

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

Przepisanie przez zmaterializowanie CTE do pośredniej tymczasowej tabeli tutaj byłoby znacznie nieproduktywne.

Zmaterializowanie definicji CTE

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

Wymagałoby skopiowania około 8GB danych do tymczasowej tabeli, wtedy nadal istnieje narzut wyboru z niej zbyt.

Przykład 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 

Powyższy przykład zajmuje około 4 minut na moim komputerze.

Tylko 15 wierszy z 1 000 000 losowo wygenerowanych wartości dopasuj predykat, ale kosztowne skanowanie tabeli zdarza się 16 razy, aby je zlokalizować.

Tutaj wpisz opis obrazka

To byłby dobry kandydat do urzeczywistnienia pośredniego wyniku. Równoważna zmiana tabeli temp trwała 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 

Z Planem

Pośrednia materializacja części zapytania do tymczasowej tabeli może być czasami przydatna, nawet jeśli jest oceniana tylko raz - kiedy pozwala na rekompilację reszty zapytania korzystając ze statystyk na zmaterializowany wynik. Przykład tego podejścia znajduje się w artykule SQL Cat kiedy rozbić złożone zapytania.

W pewnych okolicznościach SQL Server użyje bufora do buforowania pośredniego wyniku, np. CTE, i uniknie konieczności ponownej oceny tego drzewa podrzędnego. Jest to omówione w (migrated) Connect item dostarczyć podpowiedź do wymuszenia pośredniej materializacji CTE lub pochodnych tabel. Jednak nie są tworzone statystyki na ten temat i nawet jeśli liczba spooled rzędy miały znacznie różnić się od szacowanych nie jest możliwe, aby plan realizacji w toku dynamicznie dostosowywał się w odpowiedzi (przynajmniej w obecnych wersjach. Adaptacyjne plany zapytań mogą stać się możliwe w przyszłości).

 210
Author: Martin Smith,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-02-20 21:53:05

CTE ma swoje zastosowania-gdy dane w CTE są małe i istnieje duża poprawa czytelności, jak w przypadku tabel rekurencyjnych. Jednak jego wydajność nie jest z pewnością lepsza niż zmienne tabel, a gdy mamy do czynienia z bardzo dużymi stołami, tabele tymczasowe znacznie przewyższają CTE. Dzieje się tak, ponieważ nie można zdefiniować indeksów na CTE i gdy masz dużą ilość danych, które wymagają połączenia z inną tabelą (CTE jest po prostu jak makro). Jeśli łączysz się z wieloma stołami z milionami wierszy rekordów w każdym, CTE będzie działać znacznie gorzej niż tabele tymczasowe.

 53
Author: CSW,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-04-30 01:28:30

Tabele Temp są zawsze na dysku - tak długo, jak Twój CTE może być przechowywany w pamięci, najprawdopodobniej będzie szybszy(jak zmienna tabelkowa).

Ale z drugiej strony, jeśli obciążenie danych Twojego CTE (lub zmiennej tabeli temp) stanie się zbyt duże, będą one również przechowywane na dysku, więc nie ma większych korzyści.

Ogólnie rzecz biorąc, wolę CTE niż tabelę temp, ponieważ zniknął po tym, jak go użyłem. Nie muszę myśleć o tym wprost.

Więc na końcu nie ma jasnej odpowiedzi, ale osobiście wolałbym CTE niż tabele temp.

 36
Author: marc_s,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-03-30 15:20:59

Tak więc zapytanie do optymalizacji zostało napisane dwoma CTE w SQL serverze. Zajęło 28 sekund.

Spędziłem dwie minuty konwertując je do tabel temp i zapytanie zajęło 3 sekundy

Dodałem indeks do tabeli temp na polu, na którym był łączony i zmniejszyłem go do 2 sekund

Trzy minuty pracy, a teraz działa 12x szybciej, wszystko przez usunięcie CTE. Osobiście Nie będę używał CTEs, nigdy nie są one trudniejsze do debugowania.

The crazy thing is CTE były używane tylko raz i nadal umieszczanie na nich indeksu okazało się o 50% szybsze.

 8
Author: Mark Monforti,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-09-14 18:59:58

CTE nie zajmie żadnej fizycznej przestrzeni. Jest to tylko zestaw wyników, którego możemy użyć join.

Tabele Temp są tymczasowe. Możemy tworzyć indeksy, ograniczenia jak normalne tabele do tego musimy zdefiniować wszystkie zmienne.

Zakres tabeli Temp tylko w ramach sesji. EX: Otwórz dwa okno zapytania SQL

create table #temp(empid int,empname varchar)
insert into #temp 
select 101,'xxx'

select * from #temp

Uruchom to zapytanie w pierwszym oknie następnie uruchom poniższe zapytanie w drugim oknie można znaleźć różnicę.

select * from #temp
 7
Author: selvaraj,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-08-08 09:28:21

Używałem obu, ale w ogromnych skomplikowanych procedurach zawsze uważałem tabele temp za lepsze do pracy i bardziej metodyczne. CTE mają swoje zastosowania, ale na ogół z niewielkimi danymi.

Na przykład stworzyłem Zębatki, które wracają z wynikami dużych obliczeń w 15 sekund, ale konwertują ten kod do uruchomienia w CTE i widziałem, że działa ponad 8 minut, aby osiągnąć te same wyniki.

 5
Author: Andy_RC,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-09-01 14:21:02

Spóźnienie na imprezę, ale...

Środowisko, w którym pracuję jest bardzo ograniczone, wspierając niektóre produkty dostawców i dostarczając usługi o wartości dodanej, takie jak raportowanie. Ze względu na ograniczenia polityki i umowy, zwykle nie wolno mi korzystać z luksusu oddzielnej tabeli / przestrzeni danych i / lub możliwości tworzenia stałego kodu [robi się trochę lepiej, w zależności od aplikacji].

IOW, i nie mogą zazwyczaj tworzyć procedury składowane lub tabele UDFs lub temp itp. I pretty wiele trzeba zrobić wszystko za pośrednictwem mojego interfejsu aplikacji (Crystal Reports-Dodaj / link tabele, ustawić gdzie klauzule z W / W CR, itp.). Małą ratunkiem jest to, że Crystal pozwala mi używać poleceń (a także wyrażeń SQL). Niektóre rzeczy, które nie są wydajne dzięki zwykłej możliwości dodawania / łączenia tabel, można zrobić, definiując polecenie SQL. Używam CTEs przez to i uzyskałem bardzo dobre wyniki "zdalnie". CTE pomaga również w konserwacji / raportowaniu, nie wymagając, aby Kod był opracowany, przekazany dba do kompilacji, szyfrowania, transferu, instalacji, a następnie wymaga testowania wielopoziomowego. Mogę zrobić CTE przez lokalny interfejs.

Down page of using CTEs w / CR is, every report is separate. Każdy CTE musi być utrzymany dla każdego sprawozdania. Gdzie mogę zrobić SPs i UDFs, mogę stworzyć coś, co może być używane przez wiele raportów, wymagających tylko linkowania do SP i przekazywania parametrów, jak gdybyś pracował na zwykłej tabeli. CR nie jest zbyt dobry w prowadzeniu parametry do poleceń SQL, tak że aspekt CR/CTE może brakować. W takich przypadkach zwykle staram się zdefiniować CTE, aby zwrócić wystarczającą ilość danych (ale nie wszystkie dane), a następnie użyć możliwości wyboru rekordów w CR, aby pokroić i pokroić w kostkę.

Więc... mój głos jest na CTEs (dopóki nie dostanę mojej przestrzeni danych).

 4
Author: Marc,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-05-18 15:26:33

Jednym z zastosowań, w którym znalazłem doskonałą wydajność CTE, było miejsce, w którym musiałem połączyć stosunkowo złożone zapytanie do kilku tabel, które miały kilka milionów wierszy każda.

Użyłem CTE, aby najpierw wybrać podzbiór oparty na indeksowanych kolumnach, aby najpierw wyciąć te tabele do kilku tysięcy odpowiednich wierszy, a następnie dołączył CTE do mojego głównego zapytania. To wykładniczo zmniejszyło czas wykonywania moich zapytań.

Podczas gdy wyniki dla CTE nie są buforowane i zmienne tabeli mogą mieć był lepszym wyborem, naprawdę chciałem je wypróbować i znaleźć odpowiedni powyższy scenariusz.

 4
Author: purchas,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-09-06 00:32:59

Jest to naprawdę otwarte pytanie, a wszystko zależy od tego, jak jest używane i typu tabeli temp (tabela zmienna lub tradycyjna tabela).

Tradycyjna tabela temp przechowuje dane w temp DB, co spowalnia tabele temp; jednak zmienne tabel nie.

 2
Author: JoshBerke,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-03-27 16:32:09

Właśnie to przetestowałem - zarówno CTE, jak i non-CTE (gdzie zapytanie było wypisywane dla każdej instancji Unii) obie zajmowały ~31 sekund. CTE uczyniło kod znacznie bardziej czytelnym - zmniejsz go z 241 do 130 linii, co jest bardzo ładne. Z kolei tabela Temp zmniejszyła go do 132 linii, a bieg trwał pięć sekund. Nie żartuj. wszystkie te testy były buforowane - wszystkie zapytania były uruchamiane wiele razy wcześniej.

 2
Author: user2989981,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-06-09 21:39:34

Z mojego doświadczenia w SQL Server, znalazłem jeden ze scenariuszy, w których CTE przewyższa tabelę Temp

Potrzebowałem użyć zbioru danych(~100000) ze złożonego zapytania tylko raz w mojej procedurze składowanej.

  • Tabela Temp powodowała narzut na SQL gdzie moja procedura była wykonujących się powoli (ponieważ tabele Temp są rzeczywistymi tabelami zmaterializowanymi, które exist in tempdb and persistent for the life of my current procedure)

  • Z drugiej strony, z CTE, CTE utrzymują się tylko do następujące zapytanie jest uruchamiane. Tak więc CTE jest poręczną strukturą w pamięci o ograniczonej Zakres. CTE nie używa tempdb domyślnie.

Jest to jeden ze scenariuszy, w którym CTE może naprawdę pomóc uprościć kod i przewyższyć tabelę Temp. Użyłem 2 CTE, coś w stylu

WITH CTE1(ID, Name, Display) 
AS (SELECT ID,Name,Display from Table1 where <Some Condition>),
CTE2(ID,Name,<col3>) AS (SELECT ID, Name,<> FROM CTE1 INNER JOIN Table2 <Some Condition>)
SELECT CTE2.ID,CTE2.<col3>
FROM CTE2
GO
 2
Author: Amardeep Kohli,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-09-07 10:43:44