Postgresql

具有較小數據類型的表似乎在磁碟上佔用更多空間?

  • May 15, 2022

我有這兩個相同的表:

                 Table "public.region"
  Column    |   Type   | Collation | Nullable | Default 
-------------+----------+-----------+----------+---------
r_regionkey | integer      |           | not null | 
r_name      | char(25)     |           |          | 
r_comment   | char(152)     |           |          | 
Indexes:
   "region_pkey" PRIMARY KEY, btree (r_regionkey)

                 Table "public.region2"
  Column    |   Type   | Collation | Nullable | Default 
-------------+----------+-----------+----------+---------
r_regionkey | smallint |           | not null | 
r_name      | text     |           |          | 
r_comment   | text     |           |          | 
Indexes:
   "region_pkey" PRIMARY KEY, btree (r_regionkey)

我正在使用smallintandtext為了節省空間,但奇怪的是結果如下:

select pg_size_pretty(pg_table_size('region'))

返回8192 bytes

select pg_size_pretty(pg_table_size('region2'))

返回48 kB

為什麼要region2佔用更多空間,即使我使用的是smallint代替integertext代替char(n)

執行VACUUM FULL public.region;and後VACUUM FULL public.region;,再次測試:

SELECT pg_relation_size('public.region');

三個可能的問題:

  1. 顯而易見的原因:更新或刪除導致表膨脹。被 刪除VACUUM FULL
  2. 模式限定名稱(‘public.region’ 而不僅僅是 ‘region’)確保您不會在不同的模式中意外測量錯誤的表。可能不是這樣。
  3. pg_table_size()包括輔助關係叉(文件),可以為一個表填充,但不能為另一個表填充。出於您的目的,更準確的測試是pg_relation_size().

手冊:

pg_table_size ( regclass ) → bigint

計算指定表使用的磁碟空間,不包括索引(但包括其 TOAST 表(如果有)、可用空間映射和可見性映射)。

和:

pg_relation_size ( [, ] ) → relation regclassfork text``bigint

計算指定關係的一個“fork”使用的磁碟空間。pg_total_relation_size(請注意,對於大多數目的,使用更高級別的函式或更方便pg_table_size,它對所有分支的大小求和。)使用一個參數,這將返回關係的主要數據分支的大小。可以提供第二個參數來指定要檢查的分叉:

  • main返回關係的主要數據分支的大小。
  • fsm返回與關係關聯的自由空間映射的大小(參見第 70.3 節)。
  • vm返回與關係關聯的可見性地圖(參見第 70.4 節)的大小。
  • init返回與關係關聯的初始化分叉的大小(如果有)。

由於您的範例沒有TOAST 表,因此只有fsmvm有所作為。對於較大的桌子,這些尺寸通常可以忽略不計,但與您的最小測試相關。之後兩者都可能下降到“0字節” VACUUM FULL

測試更多行(數千行)。

有關的:

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