Изчисляването на размера на реда е много по-сложно от това.
Съхранението обикновено е разделено на 8 kB страници с данни . Има малки фиксирани допълнителни разходи на страница, възможни остатъци не са достатъчно големи, за да поберат друг кортеж, и по-важното мъртви редове или процент, първоначално запазен с FILLFACTOR
настройка.
И има още повече режийна реда (tuple):идентификатор на елемент от 4 байта в началото на страницата, HeapTupleHeader
от 23 байта иподравняване . Началото на заглавката на кортежа, както и началото на данните за кортежа са подравнени с кратно на MAXALIGN
, което е 8 байта на типична 64-битова машина. Някои типове данни изискват подравняване към следващото кратно на 2, 4 или 8 байта.
Цитиране на ръководството в системната таблица pg_tpye
:
typalign
е необходимото подравняване при съхраняване на стойност от този тип. То се отнася за съхранение на диск, както и за повечето представяния на стойността в PostgreSQL. Когато множество стойности се съхраняват последователно, като например при представянето на пълен ред на диска, допълването се вмъква преди дата от този тип, така че да започва от определената граница. Референцията за подравняване е началото на първата дата в последователността.Възможните стойности са:
c
=char
подравняване, т.е. не е необходимо подравняване.
s
=short
подравняване (2 байта на повечето машини).
i
=int
подравняване (4 байта на повечето машини).
d
=double
подравняване (8 байта на много машини, но в никакъв случай на всички).
Прочетете за основите в ръководството тук.
Вашият пример
Това води до 4 байта запълване след вашите 3 integer
колони, тъй като timestamp
колоната изисква double
подравняване и трябва да започне от следващото кратно на 8 байта.
И така, един ред заема:
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
Плюс идентификатор на елемент за кортеж в заглавката на страницата (както е посочено от @A.H. в коментара):
+ 4 -- item identifier in page header
------
= 52 bytes
Така стигаме до наблюдаваните 52 байта .
Изчислението pg_relation_size(tbl) / count(*)
е песимистична оценка. pg_relation_size(tbl)
включва раздуване (мъртви редове) и място, запазено от fillfactor
, както и режийни разходи за страница с данни и за таблица. (И дори не споменахме компресия за дълга varlena
данни в TOAST таблици, тъй като не се прилага тук.)
Можете да инсталирате допълнителния модул pgstattuple и да извикате SELECT * FROM pgstattuple('tbl_name');
за повече информация относно размера на таблицата и кортежа.
Свързано:
- Размер на таблицата с оформление на страницата
- Изчисляване и спестяване на място в PostgreSQL