Heaps (tabeller utan klustrade index)

Gäller för:SQL ServerAzure SQL DatabaseAzure SQL Managed InstanceSQL-databas i Microsoft Fabric

En heap är en tabell utan ett grupperat index. Du kan skapa ett eller flera icke-klustrade index på tabeller som lagras som en heap. Heapen lagrar data utan att specificera en ordning. Vanligtvis lagrar heapen initialt data i den ordning du infogar raderna. Databasmotorn kan dock flytta runt data i heapen för att lagra raderna effektivt. I frågeresultat kan du inte förutsäga dataordningen. För att garantera ordningen på de rader som returneras från en heap, använd ORDER BY. För att specificera en permanent logisk ordning för lagring av raderna, skapa ett klustrat index på tabellen, så att tabellen inte är en heap.

Note

Ibland finns goda skäl att lämna en tabell som en heap istället för att skapa ett klustrat index. Att använda heaps effektivt är dock en avancerad färdighet. De flesta tabeller bör ha ett noggrant valt klusterindex, såvida det inte finns en bra anledning att lämna tabellen som en heap.

När du ska använda en heap

En heap är idealisk för tabeller som du ofta avskär och laddar om. Database Engine optimerar utrymmet i en heap genom att fylla det tidigaste tillgängliga utrymmet.

Tänk på följande:

  • Att hitta ledigt utrymme i en heap kan vara kostsamt, särskilt om många raderingar eller uppdateringar sker.
  • Klustrade index ger stabil prestanda för tabeller som du inte ofta avkortar.

För tabeller som du regelbundet avkortar eller återskapar, såsom tillfälliga eller staging-tabeller, är det ofta mer effektivt att använda en heap.

Valet mellan att använda en heap och ett grupperat index kan avsevärt påverka databasens prestanda och effektivitet.

När du lagrar en tabell som en heap identifierar du enskilda rader med hänvisning till en 8-bytes radidentifierare (RID) bestående av filnumret, datasidnumret och platsen på sidan (FileID:PageID:SlotID). Rad-ID:t är en liten och effektiv struktur.

Använd heaps som stagingtabeller för stora, oordnade insättningsoperationer. Eftersom heaps inte upprätthåller en strikt insättningsordning är insättningsoperationen vanligtvis snabbare än en motsvarande insättning i ett klustrat index. Om du läser och bearbetar heapens data till en slutdestination, överväg att skapa ett smalt, icke-klustrat index som täcker sökpredikatet som sökfunktionen använder.

Note

Du hämtar data från en heap i ordning efter datasidor, men inte nödvändigtvis i den ordning du infogade data.

Du kan också använda heaps när du alltid får tillgång till data via icke-klustrade index och RID:n är mindre än en klustad indexnyckel.

Om en tabell är en heap och inte har några icke-klustrade index måste du läsa hela tabellen (en tabellskanning) för att hitta någon rad. SQL Server kan inte söka en RID direkt på heapen. Det här beteendet kan vara acceptabelt när tabellen är liten.

När du inte ska använda en heap

Använd inte en heap när datan ofta returneras i sorterad ordning. Ett klustrat index på sorteringskolumnen kan undvika sorteringsoperationen.

Använd inte en heap när datan ofta grupperas tillsammans. Data måste sorteras innan den grupperas, och ett klustrat index i sorteringskolumnen kan undvika sorteringsoperationen.

Använd inte en heap när dataintervall ofta efterfrågas från tabellen. Ett grupperat index i intervallkolumnen undviker att sortera hela heapen.

Använd inte en heap när det inte finns några icke-klustrade index och tabellen är stor. Den enda tillämpningen för denna design är att returnera hela tabellinnehållet utan en specificerad ordning. I en heap läser databasmotorn alla rader för att hitta en rad.

Använd inte en heap om du ofta uppdaterar datan. Om du uppdaterar en post och uppdateringen använder mer utrymme i datasidorna än den använder idag, flyttas posten till en datasida som har tillräckligt med ledigt utrymme. Denna flytt skapar en vidarebefordrad post som pekar på den nya platsen för datan. Vidarebefordrarpekaren skrivs på sidan som tidigare innehöll datan, för att ange den nya fysiska platsen. Denna rörelse introducerar fragmentering i högen. När databasmotorn söker igenom en heap följer den dessa pekare. Denna åtgärd begränsar läsprestandan och kan medföra extra I/O, vilket minskar skanningsprestandan.

Hantera heapar

Skapa en heap genom att skapa en tabell utan ett grupperat index. Om en tabell redan har ett klustrat index, ta bort det klustrade indexet för att ändra tabellen till en heap.

Om du vill ta bort en heap skapar du ett grupperat index på heapen.

Så här återskapar du en heap för att frigöra bortkastat utrymme:

  • Skapa ett klustrat index på heapen och ta sedan bort det.
  • Använd kommandot ALTER TABLE ... REBUILD för att återskapa heap.

Warning

Att skapa eller ta bort klustrade index kräver att hela tabellen skrivs om. Om tabellen har icke-klustrade index måste du återskapa alla icke-klustrade index varje gång du ändrar det klustrade indexet. Därför kan det ta mycket tid att byta från en heap till en klustrad indexstruktur eller tillbaka och kräva diskutrymme för att omordna data i tempdb.

Identifiera heap-struktur

Följande fråga returnerar en lista över heaps från den aktuella databasen. Listan innehåller:

  • Tabellnamn
  • Schemanamn
  • Antal rader
  • Tabellstorlek i KB
  • Indexstorlek i KB
  • Oanvänt utrymme
  • En kolumn för att identifiera en heap
SELECT t.name AS 'Your TableName',
       s.name AS 'Your SchemaName',
       p.rows AS 'Number of Rows in Your Table',
       SUM(a.total_pages) * 8 AS 'Total Space of Your Table (KB)',
       SUM(a.used_pages) * 8 AS 'Used Space of Your Table (KB)',
       (SUM(a.total_pages) - SUM(a.used_pages)) * 8 AS 'Unused Space of Your Table (KB)',
       CASE
           WHEN i.index_id = 0 THEN 'Yes'
           ELSE 'No'
       END AS 'Is Your Table a Heap?'
FROM sys.tables AS t
     INNER JOIN sys.indexes AS i
         ON t.object_id = i.object_id
     INNER JOIN sys.partitions AS p
         ON i.object_id = p.object_id
        AND i.index_id = p.index_id
     INNER JOIN sys.allocation_units AS a
         ON p.partition_id = a.container_id
     LEFT OUTER JOIN sys.schemas AS s
         ON t.schema_id = s.schema_id
WHERE i.index_id <= 1 -- 0 for Heap, 1 for Clustered Index
GROUP BY t.name, s.name, i.index_id, p.rows
ORDER BY 'Your TableName';

Heapstrukturer

En heap är en tabell utan ett grupperat index. Heaps har en rad i sys.partitions, med index_id = 0 för varje partition som används av heapen. Som standardinställning har en heap en enda partition. När en heap har flera partitioner har varje partition en heapstruktur som innehåller data för den specifika partitionen. Om en heap till exempel har fyra partitioner finns det fyra heapstrukturer, en i varje partition.

Beroende på datatyperna i heapen har varje heapstruktur en eller flera allokeringsenheter för att lagra och hantera data för en specifik partition. Minst har varje heap en IN_ROW_DATA allokeringsenhet per partition. Heapstrukturen har också en LOB_DATA allokeringsenhet per partition, om den innehåller stora objektkolumner (LOB). Den har också en ROW_OVERFLOW_DATA allokeringsenhet per partition, om den innehåller kolumner av variabel längd som överstiger radstorleksgränsen på 8 060 byte.

Kolumnen first_iam_page i systemvyn sys.system_internals_allocation_units pekar på den första sidan Index Allocation Map (IAM) i kedjan av IAM-sidor som hanterar utrymmet som tilldelats heapen i en specifik partition. SQL Server använder IAM-sidorna för att navigera genom heapen. Datasidorna och raderna i dem är inte i någon specifik ordning och är inte länkade. Den enda logiska anslutningen mellan datasidor är informationen som registreras på IAM-sidorna.

Important

Systemvyn sys.system_internals_allocation_units är reserverad endast för internt bruk. Framtida kompatibilitet garanteras inte.

Du kan utföra tabellskanningar eller serieläsningar av en heap genom att skanna IAM-sidorna för att hitta extents som håller sidor för heapen. Eftersom IAM representerar extents i samma ordning som de finns i datafilerna, innebär denna struktur att serial heap skannar framsteg sekventiellt genom varje fil. Att använda IAM-sidorna för att ställa in skanningssekvensen innebär också att rader från heapen vanligtvis inte returneras i den ordning de sattes in i.

Följande bild visar hur Databasmotor för SQL Server använder IAM-sidor för att hämta datarader i en enda partitions heap.

Diagram över en IAM-heap.