sql >> Databasteknik >  >> RDS >> Database

Prestandamyter:Tabellvariabler finns alltid i minnet

Gästförfattare:Derik Hammer (@SQLHammer)


nyligen bloggade Aaron Bertrand om skadliga, genomgripande SQL Server-prestandamyter. Som en förlängning av den här bloggserien kommer jag att motbevisa denna vanliga myt:

"Tabellvariabler finns alltid i minnet, därför snabbare än temporära tabeller."

Läser manualen

När jag gick direkt till källan tittade jag på Books Online-artikeln om tabeller som inkluderar tabellvariabler. Även om artikeln hänvisar till fördelarna med att använda tabellvariabler saknas det påtagligt att de är 100 % i minnet.

Ett saknat jakande innebär dock inte ett negativt. Sedan In-Memory OLTP-tabeller släpptes finns det nu mycket mer dokumentation i BOL för bearbetning i minnet. Det var där jag hittade den här artikeln om att göra temptabeller och tabellvariabler snabbare genom att använda minnesoptimering.

Hela artikeln kretsar kring hur du får dina tillfälliga objekt att använda OLTP-funktionen i minnet, och det var här jag hittade det jakande jag letade efter.

"En traditionell tabellvariabel representerar en tabell i tempdb-databasen. För mycket snabbare prestanda kan du minnesoptimera din tabellvariabel."

Tabellvariabler är inte konstruktioner i minnet. För att använda in-memory-tekniken måste du uttryckligen definiera en TYPE som är minnesoptimerad och använda den TYPEN för att definiera din tabellvariabel.

Bevisa det

Dokumentation är en sak men att se det med egna ögon är en helt annan. Jag vet att temporära tabeller skapar objekt i tempdb och kommer att skriva data till disk. Först ska jag visa dig hur det ser ut för de temporära tabellerna och sedan kommer jag att använda samma metod för att validera hypotesen att tabellvariabler fungerar på samma sätt.

Loggpostanalys

Den här frågan kommer att köra en CHECKPOINT för att ge mig en ren startpunkt och sedan visa antalet loggposter och transaktionsnamnen som finns 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;


Att köra T-SQL upprepade gånger resulterade i ett konsekvent antal tre rekord på SQL Server 2016 SP1.

Detta skapar en tillfällig tabell och visar objektposten, vilket bevisar att detta är ett riktigt 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 ska jag visa loggposterna igen. Jag kommer inte att köra CHECKPOINT-kommandot igen.

Tjugoen loggposter skrevs, vilket bevisar att dessa är skrivningar på disken, och vår CREATE TABLE är tydligt inkluderad i dessa loggposter.

För att jämföra dessa resultat med tabellvariabler kommer jag att återställa experimentet genom att köra CHECKPOINT och sedan köra nedanstående T-SQL och skapa en tabellvariabel.

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

Återigen har vi ett nytt objektsrekord. Den här gången är namnet dock mer slumpmässigt än med tillfälliga tabeller.

Det finns åttiotvå nya loggposter och transaktionsnamn som bevisar att min variabel skrivs till loggen och därför till disken.

Faktiskt i minnet

Nu är det dags för mig att få loggposterna att försvinna.

Jag skapade en OLTP-filgrupp i minnet och skapade sedan en minnesoptimerad tabelltyp.

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

Jag körde CHECKPOINT igen och skapade sedan den minnesoptimerade tabellen.

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

Efter att ha granskat loggen såg jag ingen loggaktivitet. Denna metod är faktiskt 100 % i minnet.

Ta bort

Tabellvariabler använder tempdb liknande hur temporära tabeller använder tempdb. Tabellvariabler är inte konstruktioner i minnet men kan bli dem om du använder minnesoptimerade användardefinierade tabelltyper. Ofta tycker jag att temporära tabeller är ett mycket bättre val än tabellvariabler. Den främsta anledningen till detta är att tabellvariabler inte har statistik och, beroende på SQL Server-version och inställningar, beräknas raderna vara 1 rad eller 100 rader. I båda fallen är dessa gissningar och blir skadliga delar av desinformation i din sökoptimeringsprocess.

Observera att vissa av dessa funktionsskillnader kan ändras med tiden – till exempel i nyare versioner av SQL Server kan du skapa ytterligare index på en tabellvariabel med hjälp av inline-indexsyntax. Följande tabell har tre index; primärnyckeln (klustrad som standard) och två icke-klustrade index:

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

Det finns ett bra svar på DBA Stack Exchange där Martin Smith utförligt beskriver skillnaderna mellan tabellvariabler och #temp-tabeller:

  • Vad är skillnaden mellan en temporär tabell och en tabellvariabel i SQL Server?

Om författaren

Derik är en dataprofessionell och nyskapad Microsoft Data Platform MVP med fokus på SQL Server. Hans passion fokuserar på hög tillgänglighet, katastrofåterställning, kontinuerlig integration och automatiserat underhåll. Hans erfarenhet har sträckt sig över långvarig databasadministration, konsultverksamhet och entreprenörskap som arbetar inom finans- och hälsovårdsindustrin. Han är för närvarande Senior Database Administrator med ansvar för Databas Operations-teamet vid Subway Franchise World Headquarters. När han inte är på klockan, eller bloggar på SQLHammer.com, ägnar Derik sin tid åt #sqlfamily som kapitelledare för FairfieldPASS SQL Server-användargruppen i Stamford, CT.
  1. Hur fixar jag innehållsleverantörens webbadress som inte hittas i android innehållsleverantör?

  2. PHP + SQL Server - Hur ställer man in teckenuppsättning för anslutning?

  3. DSN-filer och IRI-programvara

  4. Hur frågar man kapslade arrayer i en postgres json-kolumn?