Het berekenen van de rijgrootte is veel complexer dan dat.
Opslag is meestal verdeeld in 8 kB gegevenspagina's . Er is een kleine vaste overhead per pagina, mogelijke restanten die niet groot genoeg zijn om in een andere tuple te passen, en nog belangrijker, dode rijen of een percentage dat aanvankelijk gereserveerd is met de FILLFACTOR
instelling.
En er is nog meer overhead per rij (tuple):een item-ID van 4 bytes aan het begin van de pagina, de HeapTupleHeader
van 23 bytes en uitlijning opvulling . Het begin van de tuple-header en het begin van de tuple-gegevens worden uitgelijnd op een veelvoud van MAXALIGN
, wat 8 bytes is op een typische 64-bits machine. Sommige gegevenstypen moeten worden uitgelijnd met het volgende veelvoud van 2, 4 of 8 bytes.
Citeren van de handleiding op de systeemtabel pg_tpye
:
typalign
is de uitlijning die nodig is bij het opslaan van een waarde van dit type. Het is van toepassing op opslag op schijf en ook op de meeste representaties van de waarde in PostgreSQL. Wanneer meerdere waarden achtereenvolgens worden opgeslagen, zoals in de weergave van een volledige rij op schijf, wordt opvulling ingevoegd vóór een datum van dit type, zodat het begint op de gespecificeerde grens. De uitlijningsreferentie is het begin van het eerste gegeven in de reeks.Mogelijke waarden zijn:
c
=char
uitlijning, d.w.z. geen uitlijning nodig.
s
=short
uitlijning (2 bytes op de meeste machines).
i
=int
uitlijning (4 bytes op de meeste machines).
d
=double
uitlijning (8 bytes op veel machines, maar lang niet allemaal).
Lees hier de basisprincipes in de handleiding.
Uw voorbeeld
Dit resulteert in 4 bytes opvulling na uw 3 integer
kolommen, omdat de timestamp
kolom vereist double
uitlijning en moet beginnen bij het volgende veelvoud van 8 bytes.
Dus één rij beslaat:
23 -- heaptupleheader
+ 1 -- padding or NULL bitmap
+ 12 -- 3 * integer (no alignment padding here)
+ 4 -- padding after 3rd integer
+ 8 -- timestamp
+ 0 -- no padding since tuple ends at multiple of MAXALIGN
Plus item-ID per tuple in de paginakop (zoals aangegeven door @A.H. in de opmerking):
+ 4 -- item identifier in page header
------
= 52 bytes
Dus we komen uit op de waargenomen 52 bytes .
De berekening pg_relation_size(tbl) / count(*)
is een pessimistische schatting. pg_relation_size(tbl)
omvat bloat (dode rijen) en ruimte gereserveerd door fillfactor
, evenals overhead per gegevenspagina en per tabel. (En dan hebben we het nog niet eens gehad over compressie gedurende lange varlena
gegevens in TOAST-tabellen, omdat het hier niet van toepassing is.)
U kunt de extra module pgstattuple installeren en SELECT * FROM pgstattuple('tbl_name');
aanroepen voor meer informatie over tafel- en tupelgrootte.
Gerelateerd:
- Tabelformaat met pagina-indeling
- Ruimte berekenen en besparen in PostgreSQL