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

Kiedy powinienem używać zmiennej tabeli a tabeli tymczasowej w serwerze sql?

Twoje pytanie pokazuje, że uległeś niektórym typowym nieporozumieniom dotyczącym zmiennych tabel i tabel tymczasowych.

Napisałem dość obszerną odpowiedź na stronie DBA, patrząc na różnice między dwoma typami obiektów. To również odnosi się do twojego pytania o dysk a pamięć (nie zauważyłem żadnej znaczącej różnicy w zachowaniu między tymi dwoma).

Jeśli chodzi o pytanie w tytule, ale kiedy użyć zmiennej tabeli w porównaniu z lokalną tabelą tymczasową, nie zawsze masz wybór. Na przykład w funkcjach można używać tylko zmiennej tabeli, a jeśli potrzebujesz pisać do tabeli w zakresie podrzędnym, to tylko #temp table zrobi to (parametry wyceniane w tabeli umożliwiają dostęp tylko do odczytu).

Jeśli masz wybór, poniżej znajdziesz kilka sugestii (chociaż najbardziej niezawodną metodą jest po prostu przetestowanie obu przy określonym obciążeniu).

  1. Jeśli potrzebujesz indeksu, którego nie można utworzyć na zmiennej tabeli, będziesz oczywiście potrzebował #temporary stół. Szczegóły tego są jednak zależne od wersji. W przypadku SQL Server 2012 i starszych jedynymi indeksami, które można było utworzyć na zmiennych tabeli, były te niejawnie utworzone za pomocą UNIQUE lub PRIMARY KEY ograniczenie. SQL Server 2014 wprowadził składnię indeksu wbudowanego dla podzbioru opcji dostępnych w CREATE INDEX . Zostało to rozszerzone od tego czasu, aby umożliwić filtrowane warunki indeksowania. Indeksy z INCLUDE -d kolumny lub indeksy magazynu kolumn nadal nie są jednak możliwe do tworzenia na zmiennych tabeli.

  2. Jeśli będziesz wielokrotnie dodawać i usuwać dużą liczbę wierszy z tabeli, użyj #temporary stół. To obsługuje TRUNCATE (co jest bardziej wydajne niż DELETE dla dużych tabel) i dodatkowo kolejne wstawki po TRUNCATE mogą mieć lepszą wydajność niż te po DELETE jak pokazano tutaj.

  3. Jeśli będziesz usuwać lub aktualizować dużą liczbę wierszy, tabela tymczasowa może działać znacznie lepiej niż zmienna tabeli — jeśli jest w stanie korzystać z udostępniania zestawów wierszy (patrz przykład „Efekty udostępniania zestawów wierszy” poniżej) .
  4. Jeśli optymalny plan wykorzystujący tabelę będzie się różnić w zależności od danych, użyj #temporary stół. To wspiera tworzenie statystyk, które pozwalają na dynamiczną rekompilację planu zgodnie z danymi (chociaż w przypadku buforowanych tabel tymczasowych w procedurach składowanych zachowanie rekompilacji należy rozumieć oddzielnie).
  5. Jeśli optymalny plan dla zapytania używającego tabeli prawdopodobnie nigdy się nie zmieni, możesz rozważyć zmienną tabeli, aby pominąć obciążenie związane z tworzeniem statystyk i ponowną kompilacją (prawdopodobnie wymagałoby to wskazówek, aby naprawić żądany plan).
  6. Jeśli źródło danych wstawionych do tabeli pochodzi z potencjalnie drogiego SELECT następnie rozważ, że użycie zmiennej tabeli zablokuje możliwość korzystania z planu równoległego.
  7. Jeśli potrzebujesz danych w tabeli, aby przetrwać wycofanie transakcji użytkownika zewnętrznego, użyj zmiennej tabeli. Możliwym przypadkiem użycia tego może być rejestrowanie postępu różnych kroków w długiej partii SQL.
  8. Gdy używasz #temp tabela wewnątrz transakcji użytkownika może być utrzymywana dłużej niż w przypadku zmiennych tabeli (potencjalnie do końca transakcji vs końca instrukcji w zależności od typu blokady i poziomu izolacji), a także może zapobiec obcięciu tempdb dziennik transakcji do zakończenia transakcji użytkownika. Może to więc sprzyjać używaniu zmiennych tabeli.
  9. W ramach przechowywanych procedur można buforować zarówno zmienne tabel, jak i tabele tymczasowe. Obsługa metadanych dla buforowanych zmiennych tabeli jest mniejsza niż dla #temporary tabele. Bob Ward wskazuje w swoim tempdb prezentacja, że ​​może to spowodować dodatkową rywalizację o tabele systemowe w warunkach wysokiej współbieżności. Dodatkowo, gdy mamy do czynienia z małymi ilościami danych, może to mieć wymierną różnicę w wydajności.

Skutki udostępniania zestawu wierszy

DECLARE @T TABLE(id INT PRIMARY KEY, Flag BIT);

CREATE TABLE #T (id INT PRIMARY KEY, Flag BIT);

INSERT INTO @T 
output inserted.* into #T
SELECT TOP 1000000 ROW_NUMBER() OVER (ORDER BY @@SPID), 0
FROM master..spt_values v1, master..spt_values v2

SET STATISTICS TIME ON

/*CPU time = 7016 ms,  elapsed time = 7860 ms.*/
UPDATE @T SET Flag=1;

/*CPU time = 6234 ms,  elapsed time = 7236 ms.*/
DELETE FROM @T

/* CPU time = 828 ms,  elapsed time = 1120 ms.*/
UPDATE #T SET Flag=1;

/*CPU time = 672 ms,  elapsed time = 980 ms.*/
DELETE FROM #T

DROP TABLE #T


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Partycjonowana tabela sprawdzania serwera SQL

  2. Przetwarzaj JSON w TSQL

  3. Jak działa funkcja SOUNDEX() serwera SQL?

  4. SQL Server Typ tekstowy a typ danych varchar

  5. Jak używać funkcji CONCAT w programie SQL Server 2008 R2?