Heap-tabeller i SQL Server

i det senaste inlägget i denna bloggserie diskuterade jag vad ett B-Tree-index var och förklarade kort dess historia.

innan vi dyker in i de index som SQL Server använder är det viktigt att lägga grunden för datastrukturer. Den mest grundläggande tabellen som du kan skapa är en hög. En heap är en osorterad struktur av sidor som inte är länkade till varandra.

När ska du använda högar?

rekommendationen om bästa praxis är att undvika SQL Server-högar, i de flesta fall. Kimberly Tripp förklarar några av orsakerna och debatten här men jag kommer att täcka hög nivå. Heaps, som är den mest grundläggande lagringsstrukturen, saknar funktioner som förbättrar prestanda för normala (OLTP) arbetsbelastningar. Vissa hävdar att högar är bättre för extract, transformation och loading (ETL) – operationer eftersom det finns mindre sidor att behålla under skrivoperationer (UPDATE/INSERT/DELETE). Specifikt kan högar vara snabbare än ett B-trädindex om siduppdelningar inträffar och många nivåer i indexet måste uppdateras. Dessutom är radidentifieraren (RID), som diskuteras mer nedan, bara 8 byte. Detta kan fungera bättre än ett grupperat index med många nyckelkolumner eftersom icke-grupperade index måste lagra den grupperade nyckeln eller RID för varje indexerad rad. Vanligtvis rekommenderar jag att du använder ett grupperat index (mer om grupperade index när vi fortsätter den här serien) snarare än en hög, men om du använder dem, använd dem bara när du har bevisat att de kommer att vara effektivare än ett grupperat index. Efter att ha diskuterat en heaps struktur kommer jag att beskriva prestandaproblemen med att använda högar.

Heap struktur

en heap är en gruppering av osorterade sidor som inte är länkade. Page anatomy är utom räckhåll för denna serie eftersom alla typer av indexerade och icke-indexerade tabeller använder samma sidstruktur men jag uppmuntrar dig att kolla in här och här för att lära dig mer.

en heap består av en eller flera index allocation map (iam) sidor som pekar på de datasidor som utgör heap. Det enda undantaget från detta är när du har en rad som har uppdaterats och inte kunde passa in på sidan längre. I så fall får du en vidarebefordringspekare till raden som har flyttats till en befintlig sida med mellanslag eller en ny sida. Det är möjligt för dig att producera en kedja av vidarebefordran poster om raden fortsätter att behöva omlokalisering av ytterligare operationer.

heap-structure-1

Bildreferens: MSDN

en heap har en rad i sys.partitioner per partition och dess index_id kommer att vara lika med noll. I den här posten pekar first_iam_page på den första av sidorna index allocation map (iam). En iam sida kartor sidor för varje tilldelningsenhet och hanterar 4 GB bitar av tabellen. Tilldelningsenheter inkluderar:

  1. in_row_data allokeringsenhet
  2. LOB_DATA allokeringsenhet
  3. row_overflow_data allokeringsenhet

iam-sidan innehåller standard 96-byte-rubriken följt av IAM-rubriken. Iam-rubriken börjar med åtta slitsar för blandade fördelningar och sedan en 8000-byte bit-karta för att hitta enhetliga sträckor som tilldelats tabellen.

en blandad utsträckning är en som innehåller sidor från mer än en tabell. Detta kallas också en delad omfattning. Syftet med en blandad utsträckning är att spara utrymme med tabeller som är mindre än 64 KB. En enhetlig utsträckning är en där alla sidor i omfattningen tillhör den enda tabellen.

mixed-extent

Bildreferens: omfattningen

för att undersöka vår iam-sida måste vi först hitta den.

DBCC IND (’demo’, ’ dbo.demo’,1)

dbcc-ind

med DBCC IND har vi 17 datasidor och 1 iam-sida. Iam-sidor är inte självrefererande, därför är IAMFID (iam file Id) och iampid (iam page Id) NULL. Det betyder att vår iam-sida är i file Id (PageFID) 1 och är page Id (PagePID) 297. DBCC-sidan tillåter oss att se vår iam-sida.

DBCC TRACEON(3604);

DBCC sida (’demo’,1,297,3);

dbcc-page-iam

i gult finns åtta enkelsidiga allokeringar i vår blandade utsträckning. I ORANGE visas de enhetliga utsträckningarna i intervall.

Prestandaimplikationer

att utföra olika DML-operationer (data manipulation language) på en heap har dessa effekter.

  • infoga-nya rader kan placeras på den första tillgängliga sidan med tillräckligt med utrymme. Så när en ny rad infogas kommer den sannolikt att läggas till den sista sidan.
  • uppdatering-rader kan förbli på samma sida om den passar in på sidan efter uppdateringen, om inte kommer den att tas bort från den aktuella sidan och placeras på den första tillgängliga sidan med tillräckligt med utrymme och en vidarebefordringspekare skrivs på sin ursprungliga sida.
  • radera-Data skrivs inte över, utrymme flaggas bara som tillgängligt för återanvändning. Detta kan leda till att ditt bord förbrukar betydligt mer diskutrymme än vad som är nödvändigt.
  • välj-en tabellsökning på hela tabellen måste läsas för de flesta frågor. Undantaget från detta är när det finns ett lämpligt icke-grupperat index tillgängligt. Vi kommer att diskutera icke-klustrade index senare i denna serie.

läser

utan något stödjande index kräver en heap en fullständig tabellsökning för alla frågor. Detta beror på att den fysiska strukturen är osorterad och det finns ingen sidlänkning för att stödja intervallskanningar.

Ställ in statistik IO på

DBCC IND (’demo’,’dbo.demo’,1)

välj COUNT ( * )
från dbo.demo

upprepa vårt DBCC IND-kommando ovanifrån påminner oss om att vi har 18 sidor för den här tabellen. 17 datasidor och 1 IAM sida.

-18 radresultat, indikerar 18 sidor.

(18 rad (er) påverkade)
DBCC-körning slutförd. Om DBCC utskrivna felmeddelanden, kontakta systemadministratören.

Antal rader
—-
5031
(1 rad (s) påverkas)

tabell ’Demo’. Scan count 1, logiska läser 17, fysiska läser 0, läs framåt läser 0, lob logiska läser 0, lob fysiska läser 0, lob läs framåt läser 0.
(1 rad(er) påverkas)

notera 17 logiska läser från vår fråga. Detta beror på att iam-sidan inte räknas i den logiska läsningsmetriken och vi utförde en fullständig genomsökning av tabellen med 18 sidor.

skriver och framåt pekare

som nämnts ovan, infogar och raderar är ganska rakt framåt. En insats sker på den första sidan med tillgängligt utrymme även om det innebär att en ny sida skapas. DELETEs utförs genom att de-allokera utrymmet raden ockuperade.

uppdateringar är där saker går nedförsbacke för högar. När en datatyp med fast längd uppdateras kommer uppdateringen att ske på plats. Om en datatyp med variabel längd uppdateras och längden har ökat finns det en chans att raden inte längre får plats på samma sida. När raden inte längre passar placeras en vidarebefordringspekare i det utrymme där den ursprungliga raden var och raden flyttas till en ny sida. Denna process har en negativ inverkan på läsprestanda. Låt oss demonstrera.

ursprungligen alla våra poster i dbo.demo bord innehöll VARCHARs med 9 teckensträngar.

välj topp 5 *
från dbo.demo

 demo tabelldata

för att skapa några framåtpekare uppdaterar vi alla våra rader och ökar längden på varlen-kolumnen.

uppdatera dbo.demo
ange varLen = replikera (’a’,100)

vi har nu 95 sidor i vår heap eftersom alla våra rader har flyttats till nya sidor med framåtpekare kvar.

DBCC IND (’demo’, ’ dbo.demo’,1)

dbcc-output-1

som du kan föreställa dig, med högar som kräver fullständiga tabellskanningar, måste vi läsa mycket fler sidor för samma mängd poster nu.

Ställ in statistik IO på

välj räkna ( * )
från dbo.demo
(1 rad(s) påverkas)

tabell ’Demo’. Scan count 1, logiska läser 4405, fysiska läser 0, läsa framåt läser 0, lob logiska läser 0, lob fysiska läser 0, lob läsa framåt läser 0.

våra läsningar ökade drastiskt eftersom de ursprungliga sidorna måste läsas och sedan måste framåtpekarna följas. Prestandapåverkan och slöseri med utrymme i minnet och på disken är därför vi behöver grupperade index.

nästa gång

heap-datastrukturen är inte ett index och är ofta den värsta datastrukturen för dina tabeller i SQL Server. Vi täckte det idag som en grund för förståelse som kommer att vara användbar när vi diskuterar index. I nästa del av denna serie kommer klustrade index, en b+-trädstruktur för tabelldata, att täckas.

Lämna ett svar

Din e-postadress kommer inte publiceras.