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=charjustering, dvs. ingen justering nødvendig. -
s=shortjustering (2 bytes på de fleste maskiner). -
i=intjustering (4 bytes på de fleste maskiner). -
d=doublejustering (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