Beregning af rækkestørrelse er meget mere kompleks end som så.
Lagring er typisk opdelt i 8 kB datasider . Der er en lille fast overhead pr. side, mulige rester, der ikke er store nok til at passe til en anden tupel, og endnu vigtigere døde rækker eller en procentdel, der oprindeligt er reserveret med FILLFACTOR
indstilling.
Og der er endnu mere overhead pr. række (tuple):en element-id på 4 bytes i starten af siden, HeapTupleHeader
på 23 bytes og justeringsudfyldning . Starten af tupeloverskriften såvel som starten af tupeldata er justeret med et multiplum af MAXALIGN
, hvilket er 8 bytes på en typisk 64-bit maskine. Nogle datatyper kræver justering til det næste multiplum af 2, 4 eller 8 bytes.
Citerer manualen i systemtabellen pg_tpye
:
typalign
er den justering, der kræves ved lagring af en værdi af denne type. Den gælder for lagring på disk såvel som de fleste repræsentationer af værdien inde i PostgreSQL. Når flere værdier er lagret fortløbende, såsom i repræsentationen af en hel række på disken, indsættes udfyldning før et datum af denne type, så det begynder på den specificerede grænse. Justeringsreferencen er begyndelsen af det første datum i sekvensen.
Mulige værdier er:
-
c
=char
justering, dvs. ingen justering nødvendig. -
s
=short
justering (2 bytes på de fleste maskiner). -
i
=int
justering (4 bytes på de fleste maskiner). -
d
=double
justering (8 bytes på mange maskiner, men på ingen måde alle).
Læs om det grundlæggende i manualen her.
Dit eksempel
Dette resulterer i 4 bytes udfyldning efter dit 3 integer
kolonner, fordi timestamp
kolonne kræver double
justering og skal starte ved det næste multiplum af 8 bytes.
Så en række optager:
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 vare-id pr. tupel i sidehovedet (som påpeget af @A.H. i kommentaren):
+ 4 -- item identifier in page header
------
= 52 bytes
Så vi når frem til de observerede 52 bytes .
Beregningen pg_relation_size(tbl) / count(*)
er et pessimistisk skøn. pg_relation_size(tbl)
inkluderer bloat (døde rækker) og plads reserveret af fillfactor
, samt overhead pr. dataside og pr. tabel. (Og vi nævnte ikke engang komprimering i lang varlena
data i TOAST-tabeller, da det ikke gælder her.)
Du kan installere det ekstra modul pgstattuple og kalde SELECT * FROM pgstattuple('tbl_name');
for mere information om bord- og tupelstørrelse.
Relateret:
- Tabelstørrelse med sidelayout
- Beregning og pladsbesparelse i PostgreSQL