Osnovno o privremenim tabelama i tejbl varijablama
Objavljeno: 21-02-2014 | Autor: Milen Blagojević | Kategorija: Saveti
0
Od trenutka kada su uvedene privremene tabele i tejbl varijable u SQL Server vodi se rasprava kada je potrebno koristiti jedne a kada druge, a da bi znali odgovor na ovo pitanje potrebno je poznavati osnovne razlike između njih.
Privremene tabele su u stvari obične tabele koje se definišu i čuvaju u tempdb (sem što privremene tabele ne mogu imati FK i ne mogu se particionisati) i traju onoliko koliko traje sesija u kojoj su kreirane. Privremene tabele mogu biti:
- Lokalne – kreiraju se sa prefiksom # i vidljive su samo unutar sesije u kojoj se izvršavaju
- Globalne – kreiraju se sa prefiksom ## i vidljive su iz svih ostalih sesija
Sintaksa za kreiranje privremenih tabela:
CREATE TABLE #Temp( Id BIGINT PRIMARY KEY, Name NVARCHAR (256) )
Ukoliko se koristi više različitih privremenih tabela u okviru iste sesije moraju imati različita imena. Da bi SQL server mogao da razlikuje privremene tabele koje se kreiraju unutar iste procedure iz različitih sesija, automatski se dodaje sufiks na ime svake od njih (zato je i dužina imena privremenih tabela ograničena na 116 karaktera).
Sve trenutne privremene tabele se mogu videti:
Ili:
SELECT * FROM tempdb.sys.tables
Lokalne privremene tabele se automatski brišu po završetku sesije (ukoliko nisu eksplicitno obrisane ranije), dok se globalne privremene tabele brišu nakon završetka sesije u kojoj su kreirane i završetka svih statement-a u kojima se referenciraju te tabele.
Sa druge strane imamo tejbl varijable i one se deklarišu kao i svaka druga promenljiva:
DECLARE TABLE @Temp( Id BIGINT PRIMARY KEY, Name NVARCHAR (256))
Kao i privremene tabele i tejbl varijable se čuvaju u tempdb.
Razlike:
Tejbl varijable su vidljive samo u okviru jedne stored procedure ili batch-a u kome su deklarisane.
Privremene tabela se ne mogu koristiti unutar funkcija, dok se tejbl varijable mogu koristiti u skalarnim i tejbl funkcijama.
Tejbl varijable ne podržavaju hintove, kao npr: WITH (FORCESCAN)
Tejbl varijable ne mogu imati neklasterovane indekse, mogu se kreirati unique klasterovani indeksi i to na sledeći način:
DECLARE TABLE @Temp( Id BIGINT PRIMARY KEY, Name NVARCHAR (256), UNIQUE CLUSTERED (Name))
Ukoliko je već potrebno kreirati indeks na tejbl varijabli bolje rešenje je korišćenje privremenih tabela.
Ne mogu se kreirati default vrednosti nad kolonama tejbl varijabli.
Za razliku od table varijabli, privremene tabele je moguće koristiti u SELECT INTO statement-u:
SELECT TOP 10 [CrtacID] ,[Naziv] ,[Opis] INTO #tmpCrtaniFilmovi FROM [dbo].[CrtaniFilmovi]
SQL Server ne može kreirati statistike za tejbl varijable (statistike se koriste od strane query optimizer-a da bi se napravio najefikasniji mogući query plan na osnovu distribucije podataka). Sledeći primer to i pokazuje:
DECLARE @TmpCrtani TABLE( [CrtacID] BIGINT PRIMARY KEY, [Naziv] NVARCHAR (50), [Opis] NVARCHAR (MAX)) INSERT INTO @TmpCrtani(CrtacID, Naziv, Opis) SELECT top 100 CrtacID, Naziv, Opis FROM [dbo].[CrtaniFilmovi] SET STATISTICS PROFILE ON SELECT * FROM @TmpCrtani SET STATISTICS PROFILE OFF
Isti upit ako koristimo privremenu tabelu:
CREATE TABLE #TmpCrtani( [CrtacID] BIGINT PRIMARY KEY, [Naziv] NVARCHAR (50), [Opis] NVARCHAR (MAX)) INSERT INTO #TmpCrtani(CrtacID, Naziv, Opis) SELECT top 100 CrtacID, Naziv, Opis FROM [dbo].[CrtaniFilmovi] SET STATISTICS PROFILE ON SELECT * FROM #TmpCrtani SET STATISTICS PROFILE OFF
Ukoliko u okviru jedne transakcije izvršavamo operacije na tejbl varijablama, one se izvršavaju kao sistemske transakcije, nezavisne od transakcije koju smo mi kreirali. Ako imamo isti scenario sa privremenim tabelama, operacije nad njima će se izvršavati kao deo transakcije koju smo mi kreirali, što se može videti na sledećem primeru:
DECLARE @Temp TABLE(X INT) CREATE TABLE #Temp (X INT) BEGIN TRAN INSERT #Temp OUTPUT INSERTED.X INTO @Temp VALUES(1),(2),(3) SELECT * FROM #Temp SELECT * FROM @Temp ROLLBACK SELECT * FROM #Temp SELECT * FROM @Temp DROP TABLE #Temp
Kao što vidite, u tejbl varijabli se i dalje nalaze podaci.
Privremene tabele se kreiraju sa istim collation-om sa kojim je kreirana tempdb (ako drugačije nije navedeno), dok se tejbl varijable kreiraju u istom collation-u kao i baza nad kojom se izvršavaju. Ukoliko tempdb i korisnička baza nad kojom se ovo izvršava imaju različiti collation:
DECLARE @t TABLE( Ime NVARCHAR (55)) CREATE TABLE #t( Ime NVARCHAR (55)) INSERT INTO #t(Ime) SELECT 'Kefalo' INSERT INTO @t(Ime) SELECT 'Kefalo' SELECT * FROM #t INNER JOIN @t t ON #t.Ime = t.Ime
Doći će do sledeće greške:
Msg 468, Level 16, State 9, Line 13 Cannot resolve the collation conflict between "SQL_Latin1_General_CP1_CI_AS" and "Latin1_General_BIN" in the equal to operation.
Prilikom izvršavanja INSERT, UPDATE ili DELETE naredbi nad tejbl varijablama, SQL Server ne može generisati paralelan execution plan. Ovo itekako utiče na performanse prilikom izvršavanja upita sa velikim data setovima.
Iako nije moguće eksplicitno odrediti u kojim uslovima treba koristiti jedne a u kojim druge, neko opšte pravilo je da ukoliko radite sa malim skupovima podataka koji se ne menjaju (manje od 1000 redova) onda koristite tejbl varijable, u ostalim slučajevima treba koristiti privremene tabele.