Sqlserver
 sql >> Baza danych >  >> RDS >> Sqlserver

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

To zależy.

Przede wszystkim

Co to jest wspólne wyrażenie tabelowe?

(Nierekurencyjne) CTE jest traktowane bardzo podobnie do innych konstrukcji, które mogą być również używane jako wbudowane wyrażenia tabelowe w SQL Server. Tabele pochodne, widoki i funkcje o wartościach w tabeli wbudowanej. Zauważ, że chociaż BOL mówi, że CTE „można traktować jako tymczasowy zestaw wyników”, jest to opis czysto logiczny. Najczęściej nie jest on materializowany sam w sobie.

Co to jest stół tymczasowy?

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

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

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

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

Przepisywanie przez zmaterializowanie CTE w pośredniej tabeli tymczasowej byłoby bardzo nieproduktywne.

Materializacja definicji CTE

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

Wymagałoby to skopiowania około 8 GB danych do tabeli tymczasowej, ale nadal istnieje ryzyko wybrania z niej.

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 pasuje do predykatu, ale kosztowne skanowanie tabeli odbywa się 16 razy, aby je zlokalizować.

Byłby to dobry kandydat do zmaterializowania wyniku pośredniego. Odpowiednie przepisanie tabeli temp zajęło 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 

Pośrednia materializacja części zapytania do tabeli tymczasowej może czasami być przydatna, nawet jeśli jest oceniana tylko raz - gdy pozwala na ponowną kompilację reszty zapytania z wykorzystaniem statystyk dotyczących zmaterializowanego wyniku. Przykładem tego podejścia jest artykuł dotyczący SQL Cat Kiedy rozbijać złożone zapytania.

W pewnych okolicznościach SQL Server użyje spool do buforowania wyniku pośredniego, np. CTE i uniknąć konieczności ponownej oceny tego poddrzewa. Zostało to omówione w (zmigrowanym) elemencie Połącz. Podaj wskazówkę, jak wymusić pośrednią materializację CTE lub tabel pochodnych. Jednak nie są tworzone żadne statystyki na ten temat i nawet jeśli liczba buforowanych wierszy miałaby znacznie różnić się od oszacowanej, nie jest możliwe, aby plan wykonania w toku dynamicznie dostosowywał się w odpowiedzi (przynajmniej w obecnych wersjach. Adaptacyjne plany zapytań mogą stać się możliwe w przyszłość).



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. T-SQL — aliasowanie przy użyciu =kontra as

  2. Błąd krytyczny:wywołanie niezdefiniowanej funkcji sqlsrv_connect() w C:\xampp\htdocs

  3. Rozwiązywanie problemów z błędem Microsoft SQL Server 18456

  4. Sposoby migracji bazy danych SQL Server do Azure SQL Database

  5. Jak mogę wybrać z listy wartości w SQL Server?