Postgresql

如何確定或預測每個表行的磁碟空間?

  • May 19, 2020

我對 Postgres 很陌生,所以我的數學可以在這里關閉…

這是我的桌子:

CREATE TABLE audit (
   id BIGSERIAL PRIMARY KEY,
   content_id VARCHAR (50) NULL, 
   type VARCHAR (100) NOT NULL, 
   size bigint NOT NULL, 
   timestamp1 timestamp NOT NULL DEFAULT NOW(), 
   timestamp2 timestamp NOT NULL DEFAULT NOW()
);

我想對 1 行將佔用多少空間進行一些估計。經過一番閱讀,我想出了這個,對嗎?

1 row =
23 (heaptupleheader)
+ 1 (padding)
+ 8 (id)
+ 50 (content_id)
+ 6 (padding)
+ 100 (type)
+ 4 (padding)
+ 8 (size)
+ 8 (timestamp)
+ 8 (timestamp)
= 216 bytes

我還在本地 Postgres DB 中創建了同一張表,但數字似乎不匹配:

INSERT INTO public.audit(content_id, type, size)
   VALUES ('aaa', 'bbb', 100);

SELECT pg_size_pretty( pg_total_relation_size('audit') );  -- returns 24 kb

INSERT INTO public.audit(content_id, type, size)
   VALUES ('aaaaaaaaaaaaa', 'bbbbbbbbbbbbbb', 100000000000);

SELECT pg_size_pretty( pg_total_relation_size('audit') ); -- still returns 24 kb

這讓我想到 Postgres 保留了 24 kb 的空間,當我輸入更多數據時,一旦超過 24 kb,它會增加 132 個字節?但我內心的某些東西說這不可能。

我想看看 1 行在 Postgres db 中會佔用多少空間,這樣我就可以分析我可以在其中儲存多少數據。也許我錯過了一些非常明顯的東西。

您的計算接近最大裸行​​大小。實際範圍是每行 68 - 212 個字節,或包括索引在內的 84 - 228 個字節。

最重要的是 avarchar(n)不必佔據最大長度。數據類型是用varlena內部實現的,它為磁碟上的短字元串增加了 1 個字節的成本,加上字元串的實際字節數。

實現的數據類型varlena不需要在磁碟上進行對齊填充。

並且 NULL 值(允許content_id)實際上是免費的。看:

最後,PRIMARY KEY約束是使用標準的 btree 索引實現的。我們必須將其添加到磁碟上的總大小中。

所以磁碟上的行大小的計算是:

23 字節元組頭
1 字節填充或空點陣圖
8 字節 id BIGSERIAL PRIMARY KEY
0 - 51 字節 content_id VARCHAR (50) NULL
0 字節對齊填充
2 - 101 字節類型 VARCHAR (100) NOT NULL
? 字節對齊填充
8 字節大小 bigint 非空
8 字節時間戳 1 時間戳 NOT NULL
8 字節時間戳 2 時間戳 NOT NULL
---
最小 64(包括 6 字節填充)- 最大 208 字節(不需要填充)

+ 堆頁中的 4 字節項目標識符
---
68 - 212 字節

+ 16 個字節用於索引元組
---
84 - 228 字節

加上這些相關問題中詳述的堆頁面和索引頁面的一些成本:

磁碟上的實際行大小(沒有項目標識符):

SELECT pg_column_size(a) AS size_on_disk, *
FROM   audit a;

請注意,RAM 中的大小可能不同:

SELECT pg_column_size(content_id) AS content_id_size_on_disk
    , pg_column_size(content_id || '') AS content_id_size_in_ram
    , content_id
FROM   audit a;

看:


關於 …

這讓我想到 Postgres 保留了 24 kb 的空間來啟動

堆以 0 字節開始。索引從一個元頁面 (8kb) 開始。添加第一行後,我們看到第一個堆頁面至少有 8 kb,索引(1 個元頁面 + 第一個索引頁面)至少有 16 kb。細節在小提琴!

db<>在這裡擺弄

引用自:https://dba.stackexchange.com/questions/267413