Beräkning av radstorlek är mycket mer komplex än så.
Lagring är vanligtvis uppdelat i 8 kB datasidor . Det finns en liten fast overhead per sida, eventuella rester som inte är tillräckligt stora för att passa en annan tuppel, och ännu viktigare döda rader eller en procentandel som initialt reserverats med FILLFACTOR
inställning.
Och det finns ännu mer omkostnader per rad (tuple):en objektidentifierare på 4 byte i början av sidan, HeapTupleHeader
på 23 byte och justeringsutfyllnad . Starten av tuppelhuvudet såväl som början av tuppeldata är justerade med en multipel av MAXALIGN
, vilket är 8 byte på en typisk 64-bitars maskin. Vissa datatyper kräver justering till nästa multipel av 2, 4 eller 8 byte.
Citerar manualen i systemtabellen pg_tpye
:
typalign
är justeringen som krävs när du lagrar ett värde av denna typ. Det gäller lagring på disk såväl som de flesta representationer av värdet inuti PostgreSQL. När flera värden lagras i följd, såsom i representationen av en hel rad på disken, infogas utfyllnad före ett datum av denna typ så att det börjar på den specificerade gränsen. Inriktningsreferensen är början på den första referensen i sekvensen.Möjliga värden är:
c
=char
justering, d.v.s. ingen justering behövs.
s
=short
justering (2 byte på de flesta maskiner).
i
=int
justering (4 byte på de flesta maskiner).
d
=double
justering (8 byte på många maskiner, men inte alla).
Läs om grunderna i manualen här.
Ditt exempel
Detta resulterar i 4 byte utfyllnad efter ditt 3 integer
kolumner, eftersom timestamp
kolumnen kräver double
justering och måste börja med nästa multipel av 8 byte.
Så en rad upptar:
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 artikelidentifierare per tuppel i sidhuvudet (som påpekats av @A.H. i kommentaren):
+ 4 -- item identifier in page header
------
= 52 bytes
Så vi kommer fram till de observerade 52 byte .
Beräkningen pg_relation_size(tbl) / count(*)
är en pessimistisk uppskattning. pg_relation_size(tbl)
inkluderar bloat (döda rader) och utrymme reserverat av fillfactor
, samt overhead per datasida och per tabell. (Och vi nämnde inte ens komprimering för lång varlena
data i TOAST-tabeller, eftersom det inte gäller här.)
Du kan installera tilläggsmodulen pgstattuple och anropa SELECT * FROM pgstattuple('tbl_name');
för mer information om bord och tuppelstorlek.
Relaterat:
- Tabellstorlek med sidlayout
- Beräkna och spara utrymme i PostgreSQL