Notitie
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen u aan te melden of de directory te wijzigen.
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen de mappen te wijzigen.
van toepassing op:SQL Server
Azure SQL Database
Azure SQL Managed Instance
Vóór SQL Server 2016 (13.x) kon de gegevensgrootte in de rij van een tabel die is geoptimaliseerd voor geheugen niet langer zijn dan 8.060 bytes. Vanaf SQL Server 2016 (13.x) en in Azure SQL Database kunt u echter een tabel maken die is geoptimaliseerd voor geheugen met meerdere grote kolommen (bijvoorbeeld meerdere varbinary(8000) kolommen) en LOB-kolommen (d.z. varbinary(max), varchar(max)en nvarchar(max)) en bewerkingen uitvoeren met systeemeigen gecompileerde Transact-SQL (T-SQL) modules en tabeltypen.
Kolommen die niet passen in de limiet voor rijgrootte van 8060 bytes, worden buiten rij geplaatst in een afzonderlijke interne tabel. Elke kolom buiten rij heeft een bijbehorende interne tabel, die op zijn beurt één niet-geclusterde index heeft. Zie sys.memory_optimized_tables_internal_attributesvoor meer informatie over deze interne tabellen die worden gebruikt voor kolommen buiten rij.
Er zijn bepaalde scenario's waarin het handig is om de grootte van de rij en de tabel te berekenen:
Hoeveel geheugen een tabel gebruikt.
De hoeveelheid geheugen die door de tabel wordt gebruikt, kan niet exact worden berekend. Veel factoren zijn van invloed op de hoeveelheid geheugen die wordt gebruikt. Factoren zoals geheugentoewijzing op basis van pagina's, lokaliteit, caching en opvulling. Bovendien zijn er meerdere versies van dezelfde rij die óf gekoppeld zijn aan actieve transacties óf wachten op vuilopruiming.
De minimale grootte die nodig is voor de gegevens en indexen in de tabel, wordt gegeven door de berekening voor
<table size>
, verderop in dit artikel besproken.Het berekenen van geheugengebruik is in het beste een benadering en u wordt aangeraden capaciteitsplanning op te nemen in uw implementatieplannen.
De gegevensgrootte van een rij en past deze in de beperking van de rijgrootte van 8060 bytes? Als u deze vragen wilt beantwoorden, gebruikt u de berekening voor
<row body size>
, die verderop in dit artikel wordt besproken.
Een tabel die is geoptimaliseerd voor geheugen bestaat uit een verzameling rijen en indexen die aanwijzers naar rijen bevatten. In de volgende afbeelding ziet u een tabel met indexen en rijen, die op zijn beurt rijkoppen en hoofdteksten bevatten:
Grootte berekenen van tabel
De grootte van een tabel in het geheugen, in bytes, wordt als volgt berekend:
<table size> = <size of index 1> + ... + <size of index n> + (<row size> * <row count>)
De grootte van een hash-index is vastgesteld bij het maken van tabellen en is afhankelijk van het werkelijke aantal buckets. De bucket_count
die is opgegeven met de indexdefinitie, wordt naar boven afgerond op de dichtstbijzijnde macht van 2 om het werkelijke bucketaantalte verkrijgen. Als bucket_count
bijvoorbeeld is opgegeven als 100000, is het werkelijke aantal buckets voor de index 131072.
<hash index size> = 8 * <actual bucket count>
De grootte van een niet-geclusterde index bevindt zich in de volgorde van <row count> * <index key size>
.
De rijgrootte wordt berekend door de koptekst en de hoofdtekst toe te voegen:
<row size> = <row header size> + <actual row body size>
<row header size> = 24 + 8 * <number of indexes>
Grootte van rij berekenen
De rijen in een tabel die zijn geoptimaliseerd voor geheugen, hebben de volgende onderdelen:
De rijkoptekst bevat het tijdstempel dat nodig is voor het implementeren van rijversies. De rijkop bevat ook de indexpointer voor het implementeren van de rijkoppeling in de hash-buckets (eerder beschreven).
De hoofdtekst van de rij bevat de werkelijke kolomgegevens, waaronder enkele aanvullende informatie, zoals de null-matrix voor null-kolommen en de offsetmatrix voor gegevenstypen met variabele lengte.
In de volgende afbeelding ziet u de rijstructuur voor een tabel met twee indexen:
De begin- en eindtijdstempels geven de periode aan waarin een bepaalde rijversie geldig is. Transacties die in dit interval beginnen, kunnen deze rijversie zien. Zie Transacties met Memory-Optimized Tabellenvoor meer informatie.
De indexpointers wijzen naar de volgende rij in de keten die hoort bij de hash-bucket. In de volgende afbeelding ziet u de structuur van een tabel met twee kolommen (naam, plaats) en met twee indexen, één op de kolomnaam en één op de plaats van de kolom.
In deze afbeelding worden de namen John
en Jane
naar de eerste bucket gehasht.
Susan
wordt gehasht naar de tweede bucket. De steden Beijing
en Bogota
worden gehasht naar de eerste datasetbucket.
Paris
en Prague
worden gehashd naar de tweede bucket.
De ketens voor de hash-index op naam zijn dus als volgt:
- Eerste bucket:
(John, Beijing)
;(John, Paris)
;(Jane, Prague)
- Tweede bucket:
(Susan, Bogota)
De ketens voor de index op stad zijn als volgt:
- Eerste bucket:
(John, Beijing)
,(Susan, Bogota)
- Tweede bucket:
(John, Paris)
,(Jane, Prague)
Een eindtijdstempel ∞ (oneindigheid) geeft aan dat dit de huidige geldige versie van de rij is. De rij is niet bijgewerkt of verwijderd sinds deze rijversie is geschreven.
De tabel bevat de volgende rijen voor een tijd die groter is dan 200
:
Naam | Stad |
---|---|
John | Peking |
Jane | Praag |
Echter, voor elke actieve transactie met begintijd 100
, raadpleeg de volgende versie van de tabel:
Naam | Stad |
---|---|
John | Parijs |
Jane | Praag |
Susan | Bogota |
De berekening van <row body size>
wordt in de volgende tabel besproken.
Er zijn twee verschillende berekeningen voor de maat van de rij: de berekende grootte en de werkelijke grootte.
De berekende grootte, aangeduid met berekende rijtekstgrootte, wordt gebruikt om te bepalen of de limiet voor de rijgrootte van 8.060 bytes wordt overschreden.
De werkelijke grootte, aangeduid met werkelijke grootte van het rijlichaam, is de feitelijke opslaggrootte van het rijlichaam in het geheugen en in de controlepuntbestanden.
Zowel berekende rijbodygrootte als werkelijke rijbodygrootte worden op dezelfde manier berekend. Het enige verschil is de berekening van de grootte van (n)varchar(i) en varbinary(i) kolommen, zoals onderaan de volgende tabel wordt weergegeven. De berekende grootte van de rijtekst maakt gebruik van de gedeclareerde grootte i als de grootte van de kolom, terwijl de werkelijke grootte van de rijtekst de werkelijke grootte van de gegevens gebruikt.
In de volgende tabel wordt de berekening van de grootte van de rijtekst beschreven, gegeven als <actual row body size> = SUM(<size of shallow types>) + 2 + 2 * <number of deep type columns>
.
Afdeling | Grootte | Opmerkingen |
---|---|---|
Ondiepe type kolommen |
SUM(<size of shallow types>) . De grootte in bytes van de afzonderlijke typen is als volgt:bit: 1 tinyint: 1 kleine: 2 int: 4 echte: 4 smalldatetime-: 4 smallmoney: 4 bigint: 8 datum/tijd-: 8 datum/tijd2-: 8 float: 8 geld: 8 numerieke (precisie <= 18): 8 tijd: 8 numeriek(precisie > 18): 16 uniqueidentifier: 16 |
|
ondiepe kolomopvulling | Mogelijke waarden zijn:1 als er diepe typekolommen zijn en de totale gegevensgrootte van de ondiepe kolommen als oneven getal is.anders 0 |
Deep types zijn de types (var)binary en (n)(var)char. |
verschuivingsmatrix voor kolommen met dieptetypen | Mogelijke waarden zijn:0 als er geen diepe type kolommen zijnanders 2 + 2 * <number of deep type columns> |
Deep types zijn de typen (var)binary en (n)(var)char. |
Null-matrix |
<number of nullable columns> / 8 afgerond naar volledige bytes. |
De matrix heeft 1 bits per nullable kolom. Dit wordt afgerond op volledige bytes. |
null-matrixopvulling | Mogelijke waarden zijn:1 als er dieptekolommen zijn en de grootte van de NULL matrix een oneven aantal bytes is.anders 0 |
Deep types zijn de typen (var)binary en (n)(var)char. |
opvulling | Als er geen dieptekolommen zijn: 0 Als er diepe typekolommen zijn, wordt 0-7 bytes opvulling toegevoegd op basis van de grootste uitlijning die vereist is door een ondiepe kolom. Elke ondiepe kolom vereist uitlijning die gelijk is aan de grootte die eerder is gedocumenteerd, behalve dat GUID-kolommen uitlijning van 1 byte (niet 16) en numerieke kolommen altijd uitlijning van 8 bytes nodig hebben (nooit 16). De grootste uitlijningsvereiste voor alle ondiepe kolommen wordt gebruikt. 0 - 7 bytes opvulling wordt zodanig toegevoegd dat de totale grootte tot nu toe (zonder de dieptetypekolommen) een veelvoud van de vereiste uitlijning is. |
Diepe typen zijn de typen (var)binary en (n)(var)char. |
dieptekolommen met vaste lengte | SUM(<size of fixed length deep type columns>) De grootte van elke kolom is als volgt: i voor char(i) en binary(i).2 * i voor nchar(i) |
Dieptekolommen met vaste lengte zijn kolommen van het type char(i), nchar(i)of binary(i). |
kolommen met een dieptetype variabele lengte berekende grootte | SUM(<computed size of variable length deep type columns>) De berekende grootte van elke kolom is als volgt: i voor varchar(i) en varbinary(i)2 * i voor nvarchar(i) |
Deze rij is alleen van toepassing op de berekende grootte van de rijbody . Kolommen met een dieptetype met variabele lengte zijn kolommen van het type varchar(i), nvarchar(i)of varbinary(i). De berekende grootte wordt bepaald door de maximale lengte ( i ) van de kolom. |
kolommen met een variabele dieptetype en lengte werkelijke grootte | SUM(<actual size of variable length deep type columns>) De werkelijke grootte van elke kolom is als volgt: n , waarbij n het aantal tekens is dat in de kolom is opgeslagen, voor varchar(i).2 * n , waarbij n het aantal tekens is dat is opgeslagen in de kolom, voor nvarchar(i).n , waarbij n het aantal bytes is dat in de kolom is opgeslagen, voor varbinary(i). |
Deze rij geldt alleen voor de werkelijke grootte van de rijhoofdtekst . De werkelijke grootte wordt bepaald door de gegevens die zijn opgeslagen in de kolommen in de rij. |
Voorbeeld: Berekening van tabel- en rijgrootte
Voor hash-indexen wordt het werkelijke aantal buckets afgerond op de dichtstbijzijnde macht van 2. Als de opgegeven bucket_count
bijvoorbeeld 100000 is, wordt het werkelijke aantal buckets voor de index 131072.
Overweeg een tabel Orders met de volgende definitie:
CREATE TABLE dbo.Orders (
OrderID INT NOT NULL PRIMARY KEY NONCLUSTERED,
CustomerID INT NOT NULL INDEX IX_CustomerID HASH WITH (BUCKET_COUNT = 10000),
OrderDate DATETIME NOT NULL,
OrderDescription NVARCHAR(1000)
)
WITH (MEMORY_OPTIMIZED = ON);
GO
Deze tabel heeft één hash-index en een niet-geclusterde index (de primaire sleutel). Het bevat ook drie kolommen met een vaste lengte en één kolom met een variabele lengte, waarbij een van de kolommen NULL
able (OrderDescription
). Stel dat de Orders
tabel 8.379 rijen heeft en dat de gemiddelde lengte van de waarden in de kolom OrderDescription
78 tekens is.
Als u de tabelgrootte wilt bepalen, moet u eerst de grootte van de indexen bepalen. De bucket_count
voor beide indexen is opgegeven als 10000. Dit wordt afgerond op de dichtstbijzijnde macht van 2: 16384. Daarom is de totale grootte van de indexen voor de Orders
tabel:
8 * 16384 = 131072 bytes
Wat er overblijft, is de grootte van de tabelgegevens. Dit is:
<row size> * <row count> = <row size> * 8379
(De voorbeeldtabel heeft 8.379 rijen.) Nu hebben we:
<row size> = <row header size> + <actual row body size>
<row header size> = 24 + 8 * <number of indices> = 24 + 8 * 1 = 32 bytes
Vervolgens gaan we <actual row body size>
berekenen:
Ondiepe typekolommen:
SUM(<size of shallow types>) = 4 <int> + 4 <int> + 8 <datetime> = 16
Ondiepe kolomopvulling is 0, omdat de totale ondiepe kolomgrootte een even getal is.
Verschuivingmatrix voor kolommen met dieptetypen:
2 + 2 * <number of deep type columns> = 2 + 2 * 1 = 4
NULL
array = 1NULL
matrixopvulling = 1, omdat deNULL
matrixgrootte oneven is en er een diepe typekolom is.Opvulling
- 8 is de grootste uitlijningsvereiste
- Grootte tot nu toe is 16 + 0 + 4 + 1 + 1 = 22
- Dichtstbijzijnde veelvoud van 8 is 24
- Totaal opvulling is 24 - 22 = 2 bytes
Er zijn geen kolommen met een dieptetype met vaste lengte (kolommen met een dieptetype met vaste lengte: 0.).
De daadwerkelijke grootte van de dieptekolom is 2 * 78 = 156. De kolom met één dieptetype
OrderDescription
heeft het typenvarchar
.
<actual row body size> = 24 + 156 = 180 bytes
De berekening voltooien:
<row size> = 32 + 180 = 212 bytes
<table size> = 8 * 16384 + 212 * 8379 = 131072 + 1776348 = 1907420
De totale tabelgrootte in het geheugen is dus ongeveer 2 megabytes. Dit houdt geen rekening met mogelijke overhead die wordt gemaakt door geheugentoewijzing en eventuele rijversies die vereist zijn voor de transacties die toegang hebben tot deze tabel.
Het werkelijke geheugen dat is toegewezen voor en gebruikt door deze tabel en de bijbehorende indexen, kan worden verkregen via de volgende query:
SELECT * FROM sys.dm_db_xtp_table_memory_stats
WHERE object_id = object_id('dbo.Orders');
Beperkingen voor kolom buiten rij
Bepaalde beperkingen en beperkingen voor het gebruik van kolommen buiten rij in een tabel die is geoptimaliseerd voor geheugen, worden als volgt weergegeven:
- Als er een columnstore-index is voor een tabel die is geoptimaliseerd voor geheugen, moeten alle kolommen in de rij passen.
- Alle indexsleutelkolommen moeten in rij worden opgeslagen. Als een indexsleutelkolom niet in rij past, mislukt het toevoegen van de index.
- Opmerkingen over het wijzigen van een voor geheugen geoptimaliseerde tabel met kolommen buiten de rij.
- Voor LOBs komt de groottebeperking overeen met die van op schijf gebaseerde tabellen (een limiet van 2 GB voor LOB-waarden).
- Voor optimale prestaties raden we u aan dat de meeste kolommen binnen 8.060 bytes moeten passen.
- Gegevens buiten de rij kunnen overmatig geheugen- en/of schijfgebruik veroorzaken.