sql >> Database teknologi >  >> RDS >> Database

Ydeevnemyter:Tabelvariabler er altid i hukommelsen

Gæsteforfatter:Derik Hammer (@SQLHammer)


For nylig bloggede Aaron Bertrand om skadelige, gennemgribende SQL Server Performance Myths. Som en forlængelse af denne blogserie vil jeg afkræfte denne almindelige myte:

"Tabelvariable er altid i hukommelsen, derfor hurtigere end midlertidige tabeller."

Læsning af manualen

Da jeg gik direkte til kilden, kiggede jeg på Books Online-artiklen om tabeller, som inkluderer tabelvariable. Selvom artiklen refererer til fordelene ved at bruge tabelvariabler, mangler det iøjnefaldende, at de er 100 % i hukommelsen.

En manglende bekræftelse indebærer dog ikke en negativ. Siden In-Memory OLTP-tabeller blev frigivet, er der nu meget mere dokumentation i BOL til in-memory-behandling. Det er der, jeg fandt denne artikel om at gøre temp tabel- og tabelvariabler hurtigere ved at bruge hukommelsesoptimering.

Hele artiklen kredser om, hvordan du får dine midlertidige objekter til at bruge OLTP-funktionen i hukommelsen, og det er her, jeg fandt det bekræftende, jeg ledte efter.

"En traditionel tabelvariabel repræsenterer en tabel i tempdb-databasen. For meget hurtigere ydeevne kan du hukommelsesoptimere din tabelvariabel."

Tabelvariabler er ikke konstruktioner i hukommelsen. For at bruge in-memory-teknologien skal du udtrykkeligt definere en TYPE, som er hukommelsesoptimeret, og bruge denne TYPE til at definere din tabelvariabel.

Bevis det

Dokumentation er én ting, men at se det med mine egne øjne er noget helt andet. Jeg ved, at midlertidige tabeller opretter objekter i tempdb og vil skrive data til disk. Først vil jeg vise dig, hvordan det ser ud for de midlertidige tabeller, og derefter vil jeg bruge den samme metode til at validere hypotesen om, at tabelvariabler virker på samme måde.

Analyse af logposter

Denne forespørgsel vil køre et CHECKPOINT for at give mig et rent udgangspunkt og derefter vise antallet af logposter og transaktionsnavne, der findes i loggen.

USE tempdb;
GO
 
CHECKPOINT;
GO
 
SELECT COUNT(*) [Count] 
  FROM sys.fn_dblog (NULL, NULL);
 
SELECT [Transaction Name]
  FROM sys.fn_dblog (NULL, NULL)
  WHERE [Transaction Name] IS NOT NULL;


Kørsel af T-SQL gentagne gange resulterede i en konsekvent tælling af tre rekorder på SQL Server 2016 SP1.

Dette opretter en midlertidig tabel og viser objektposten, hvilket beviser, at dette er et rigtigt objekt i tempdb.

USE tempdb;
GO
 
DROP TABLE IF EXISTS #tmp;
GO
 
CREATE TABLE #tmp (id int NULL);
 
SELECT name
  FROM sys.objects o
  WHERE is_ms_shipped = 0;

Nu vil jeg vise logposterne igen. Jeg vil ikke køre CHECKPOINT-kommandoen igen.

Der blev skrevet 21 logposter, hvilket beviser, at disse er skrivninger på disken, og vores CREATE TABLE er tydeligt inkluderet i disse logposter.

For at sammenligne disse resultater med tabelvariable vil jeg nulstille eksperimentet ved at køre CHECKPOINT og derefter udføre nedenstående T-SQL og oprette en tabelvariabel.

USE tempdb;
GO
 
DECLARE @var TABLE (id int NULL);
 
SELECT name
  FROM sys.objects o
  WHERE is_ms_shipped = 0;

Endnu en gang har vi en ny objektrekord. Denne gang er navnet dog mere tilfældigt end med midlertidige tabeller.

Der er 82 nye logposter og transaktionsnavne, der beviser, at min variabel bliver skrevet til loggen og derfor til disken.

Faktisk i hukommelsen

Nu er det tid for mig at få logposterne til at forsvinde.

Jeg oprettede en OLTP-filgruppe i hukommelsen og oprettede derefter en hukommelsesoptimeret tabeltype.

USE Test;
GO
 
CREATE TYPE dbo.inMemoryTableType  
  AS TABLE 
  ( id INT NULL INDEX ix1 )
  WITH (MEMORY_OPTIMIZED = ON);  
GO

Jeg udførte CHECKPOINT igen og oprettede derefter den hukommelsesoptimerede tabel.

USE Test;
GO
 
DECLARE @var dbo.inMemoryTableType;
 
INSERT INTO @var (id) VALUES (1)
 
SELECT * from @var;  
GO

Efter at have gennemgået loggen, så jeg ingen logaktivitet. Denne metode er faktisk 100 % i hukommelsen.

Take away

Tabelvariabler bruger tempdb svarende til hvordan midlertidige tabeller bruger tempdb. Tabelvariabler er ikke konstruktioner i hukommelsen, men kan blive dem, hvis du bruger hukommelsesoptimerede brugerdefinerede tabeltyper. Ofte synes jeg, at midlertidige tabeller er et meget bedre valg end tabelvariable. Hovedårsagen til dette er, at tabelvariabler ikke har statistik, og afhængigt af SQL Server-version og indstillinger, regner rækkeestimaterne ud til at være 1 række eller 100 rækker. I begge tilfælde er disse gæt og bliver skadelige stykker misinformation i din forespørgselsoptimeringsproces.

Bemærk, at nogle af disse funktionsforskelle kan ændre sig over tid - for eksempel i nyere versioner af SQL Server kan du oprette yderligere indekser på en tabelvariabel ved hjælp af inline indekssyntaks. Følgende tabel har tre indekser; den primære nøgle (klyngede som standard) og to ikke-klyngede indekser:

DECLARE @t TABLE
(
  a int PRIMARY KEY,
  b int,
  INDEX x (b, a DESC),
  INDEX y (b DESC, a)
);

Der er et godt svar på DBA Stack Exchange, hvor Martin Smith udtømmende beskriver forskellene mellem tabelvariabler og #temp-tabeller:

  • Hvad er forskellen mellem en midlertidig tabel og tabelvariabel i SQL Server?

Om forfatteren

Derik er en dataprofessionel og nyudviklet Microsoft Data Platform MVP med fokus på SQL Server. Hans passion fokuserer på høj tilgængelighed, katastrofegendannelse, kontinuerlig integration og automatiseret vedligeholdelse. Hans erfaring har spændt over langsigtet databaseadministration, rådgivning og iværksættervirksomhed, der arbejder i finans- og sundhedsindustrien. Han er i øjeblikket Senior Database Administrator med ansvar for Database Operations-teamet på Subway Franchise World Headquarters. Når han ikke er på uret eller blogger på SQLHammer.com, afsætter Derik sin tid til #sqlfamily som kapitelleder for FairfieldPASS SQL Server-brugergruppen i Stamford, CT.
  1. Oracle Apex 5.0 - Vis statisk billede

  2. Hvordan indstiller man en maksimal udførelsestid for en mysql-forespørgsel?

  3. Vil du gemme PHP-array til MySQL?

  4. Hvad er en lagret procedure?