Pokazywanie postów oznaczonych etykietą Table. Pokaż wszystkie posty
Pokazywanie postów oznaczonych etykietą Table. Pokaż wszystkie posty

wtorek, 19 sierpnia 2014

T-SQL: Tabele tymczasowe, zmienne typu TABLE, różnice

Język T-SQL umożliwia tworzenie tabel tymczasowych oraz zmiennych typu TABLE.

Tabele tymczasowe dzielimy na:

#lokalne - do których dostęp posiadamy w ramach otwartej sesji

##globalne - dostępne w ramach SERWERA (czyli będzie ona dostępna również w ramach innej bazy).

@zmienne typu TABLE - dostępne od chwili wywołania do zakończenia działania skryptu

Pierwsza różnica pomiędzy tabelami tymczasowymi a zmiennymi: tabele tymczasowe TWORZYMY, a zmienne DEKLARUJEMY.

Składnia tworzenia tabel tymczasowych:

CREATE TABLE #NAZWA_TABELI
(
kolumna1   typ,
kolumna2   typ,
...
kolumnaN, typ )

warto też pamiętać, że możemy od razu przekazać dane z zapytania do tabeli tymczasowej, bez konieczności podawania jej definicji, dodając przed FROM magiczne "INTO #TABELA", np

CREATE TABLE #TEMP 
(
NAME NVARCHAR(100) 
)
SELECT
name, surname, age

FROM PERSON

możemy zastąpić

SELECT
name, surname, age
INTO #TEMP
FROM PERSON


Wówczas tabela tymczasowa utworzy się sama, a jej kolumny będą odpowiadały nazwom kolumn zwracanych przez kwerendę. Należy wówczas pamiętać o dwóch podstawowych zasadach:
  1. Wszystkie zwracane kolumny w kwerendzie muszą posiadać nazwy
  2. Nazwy kolumn muszą być unikatowe (nie mogą się powtórzyć)



W przypadku deklarowania zmiennej typu TABLE:

DECLARE @NAZWA_TABELI TABLE
(
kolumna1   typ,
kolumna2   typ,
...
kolumnaN, typ
)

Zastosowanie

Zapewne niejednokrotnie pojawiała się potrzeba tworzenia tabel "na chwilę". Możemy oczywiście tworzyć pewne tabele, nazwać je "tymczasowe" i wierzyć, że kiedyś je usuniemy :) Niemniej jednak takie rozwiązanie jest mało eleganckie, niejednokrotnie później pozostają dziwne byty, których boimy się usunąć, a które w rzeczywistości utworzyliśmy na 5 minut...

Tabele tymczasowe wprost świetnie nadają się do importów i migracji danych pomiędzy środowiskami oraz analizy danych, gdzie operujemy już na jednym, stałym, wstępnie ograniczonym "wiaderku danych", do których możemy co jakiś czas później się ponownie odwołać.


Zmienne natomiast mają dość krótki żywot (do zakończenia działania skryptu) :) Niemniej jednak są w teorii bardziej wydajne, ponieważ w przypadku SQL SERVER przechowywane są w pamięci operacyjnej do chwili zakończenia działania skryptu. Jeśli zaraz po wykonaniu zapytania dane nie będą nam już potrzebne, zmienna może okazać się niezłym pomysłem. Są one szczególnie fajne przy mniejszych zbiorach, np. gdy nie chcemy operować korzystać z kursorów do poruszania się po danych (a kysz!) - wówczas odpowiednia pętla po naszym "mikro zbiorze" i po krzyku.



Który rodzaj wybrać?

Zmienne typu TABLE powinniśmy stosować, gdy przekazujemy tablicę jako parametr do procedury czy funkcji. Ponadto zmienna "znika" po wykonaniu skryptu.

Przy tabelach tymczasowych powinniśmy dodatkowo pamiętać o konieczności ich usunięcia, gdy nie są już potrzebne.

Jeśli chcielibyśmy posiadać dostęp do naszej tabeli tymczasowej globalnie (np. migracja danych, głębsze analizy itd), oczywistym jest, że powinniśmy stosować ##, jednakże tylko w sytuacji, kiedy faktycznie będziemy korzystali z tabeli tymczasowej później.

Warto też pamiętać, że tabele tymczasowe możemy wykorzystać do złączeń (JOIN). Możemy dzięki temu łączyć już przefiltrowany zbiór pewnych danych z tabeli/tabel (np słowników) w formie #tabeli_tymczasowej, z głównym źródłem - praktyczne przy dużych słownikach, z których interesuje nas niewielki ich fragment.

Wydajność

Pod względem wydajności, nie istnieje uniwersalne uzasadnienie, kiedy powinniśmy korzystać z tabel tymczasowych # / ##, a kiedy ze zmiennych. W google można odnaleźć masę rankingów na temat szybkości działania.
Zmienne przechowywane są w pamięci (chyba że przekroczą określony rozmiar - wówczas trafią do tempdb), więc w teorii powinny być szybsze.
Nie przeprowadzałem wystarczającej ilości prób, aby jednoznacznie powiedzieć, kiedy stosować @, a kiedy #.

Osobiście uważam, że optymalnym rozwiązaniem będzie przetestowanie "na żywo" i po prostu - wybranie szybszego rozwiązania per-case. Osobiście wielokrotnie byłem zaskoczony rezultatem działania. Od razu przypomina mi się cudowny cytat, który kiedyś gdzieś usłyszałem:

W teorii, teoria i praktyka to to samo. 
W praktyce, tak nie jest.