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. Ett eller flera icke-grupperade index kan skapas i tabeller som lagras i heapform. Data lagras i heapen utan att specificera någon ordning. Vanligtvis lagras data ursprungligen i den ordning raderna infogas. Databasmotorn kan dock flytta runt data i heapen för att lagra raderna effektivt. I frågeresultat kan dataordningen inte förutsägas. För att garantera ordningen på de rader som returneras från en heap, använd ORDER BY. Om du vill ange en permanent logisk ordning för att lagra raderna skapar du ett grupperat index i tabellen så att tabellen inte är en heap.

Note

Det finns ibland goda skäl att lämna en tabell som en heap i stället för att skapa ett grupperat index, men att använda heaps effektivt är 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 ofta raderas och läses in igen. Databasmotorn optimerar utrymmet i en heap genom att fylla det först tillgängliga utrymmet.

Tänk på följande:

  • Det kan vara dyrt att hitta ledigt utrymme i en heap, särskilt om det har gjorts många borttagningar eller uppdateringar.
  • Grupperade index ger stabila prestanda för tabeller som inte trunkeras ofta.

För tabeller som regelbundet trunkeras eller återskapas, till exempel tillfälliga tabeller eller mellanlagringstabeller, är det ofta mer effektivt att använda en hög.

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

När en tabell lagras som en heap identifieras enskilda rader med referens till en 8-bytes radidentifierare (RID) som består av filnumret, datasidans nummer och facket på sidan (FileID:PageID:SlotID). Rad-ID:t är en liten och effektiv struktur.

Heaps kan användas som mellanlagringstabeller för stora, osorterade infogningsåtgärder. Eftersom data infogas utan att tvinga fram en strikt ordning är infogningsåtgärden vanligtvis snabbare än motsvarande infogning i ett grupperat index. Om heapens data ska läsas och bearbetas för ett slutmål kan det vara användbart att skapa ett smalt icke-klustrat index som täcker sökpredikatet som används av frågan.

Note

Data hämtas från en heapstruktur i ordning efter datasidor, men inte nödvändigtvis i vilken ordning data infogades.

Ibland använder dataexperter också högar när data alltid nås via icke-grupperade index, och RID är mindre än en klustrad indexnyckel.

Om en tabell är en heap och inte har några icke-grupperade index måste hela tabellen läsas (en tabellgenomsökning) för att hitta en rad. SQL Server kan inte söka efter 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 data ofta returneras i sorterad ordning. Ett grupperat index i sorteringskolumnen kan undvika sorteringsåtgärden.

Använd inte en heap när data ofta grupperas tillsammans. Data måste sorteras innan de grupperas och ett grupperat index i sorteringskolumnen kan undvika sorteringsåtgärden.

Använd inte en heap när dataområden ofta hämtas 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. Det enda programmet för den här designen är att returnera hela tabellinnehållet utan någon angiven ordning. I en heap läser databasmotorn alla rader för att hitta en rad.

Använd inte en heap om data uppdateras ofta. Om du uppdaterar en post och uppdateringen använder mer utrymme på datasidorna än de använder för närvarande måste posten flyttas till en datasida som har tillräckligt med ledigt utrymme. Detta skapar en vidarebefordrad post som pekar på den nya platsen för data, och vidarebefordrande pekare måste skrivas på sidan som lagrade dessa data tidigare, för att indikera den nya fysiska platsen. Detta leder till fragmentering i högen. När databasmotorn söker igenom en heap följer den dessa pekare. Den här åtgärden begränsar prestandan för läsframåt och kan medföra ytterligare I/O som minskar prestandan vid genomsökning.

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-grupperade index måste alla icke-grupperade index återskapas när det klustrade indexet ändras. 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 omorganisera 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 t
INNER JOIN sys.indexes i
    ON t.object_id = i.object_id
INNER JOIN sys.partitions p
    ON i.object_id = p.object_id
        AND i.index_id = p.index_id
INNER JOIN sys.allocation_units a
    ON p.partition_id = a.container_id
LEFT JOIN sys.schemas 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. Varje heap har minst en IN_ROW_DATA allokeringsenhet per partition. Heapen 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 med variabel längd som överskrider storleksgränsen på 8 060 byte.

Kolumnen first_iam_page i sys.system_internals_allocation_units systemvyn pekar på den första IAM-sidan i kedjan med IAM-sidor som hanterar utrymmet som har disponerats för 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 endast reserverad för intern ANVÄNDNING av SQL Server. Framtida kompatibilitet garanteras inte.

Tabellgenomsökningar eller serieläsningar av en heap kan utföras genom att genomsöka IAM-sidorna för att hitta de utsträckningar som innehåller sidor för heapen. Eftersom IAM representerar extenter i samma ordning som de finns i datafilerna innebär det att serielle heapgenomsökningar fortskrider sekventiellt genom varje fil. Om du använder IAM-sidorna för att ange genomsökningssekvensen innebär det också att rader från heapen vanligtvis inte returneras i den ordning som de infogades.

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

iam_heap

SKAPA INDEX (Transact-SQL)
DROP-INDEX (Transact-SQL)
Beskrivning av grupperade och icke-grupperade index