Postgresql

對於對齊優化表大於原始表 - 為什麼?

  • September 19, 2014

另一個問題中,我了解到我應該從我的一個表中優化佈局以節省空間並獲得更好的性能。我這樣做了,但最終得到了一個比以前更大的表,並且性能沒有改變。當然我做了一個VACUUM ANALYZE。怎麼會?

(我發現如果我只索引單個列,索引大小不會改變。)

這是我來自的表格(我添加了尺寸+填充):

                              Table "public.treenode"
   Column     |           Type           | Size |          Modifiers
---------------+--------------------------+------+-------------------------------
id            | bigint                   | 8    | not null default nextval( ...
user_id       | integer                  | 4+4  | not null
creation_time | timestamp with time zone | 8    | not null default now()
edition_time  | timestamp with time zone | 8    | not null default now()
project_id    | integer                  | 4    | not null
location      | real3d                   | 36   | not null
editor_id     | integer                  | 4+4  |
parent_id     | bigint                   | 8    |
radius        | real                     | 4    | not null default 0
confidence    | smallint                 | 2    | not null default 5
skeleton_id   | integer                  | 4    | not null

隨著real3d被定義為

CREATE TYPE real3d AS (
 x real,
 y real,
 z real);

我將此佈局更改為以下內容:

                               Table "public.treenode_new"
   Column     |           Type           | Size |            Modifiers
---------------+--------------------------+------+--------------------------------
id            | bigint                   | 8    | not null default nextval(' ...
project_id    | integer                  | 4    | not null
location_x    | real                     | 4    | not null
location_y    | real                     | 4    | not null
location_z    | real                     | 4    | not null
editor_id     | integer                  | 4    | not null
user_id       | integer                  | 4    | not null
creation_time | timestamp with time zone | 8    | not null default now()
edition_time  | timestamp with time zone | 8    | not null default now()
skeleton_id   | integer                  | 4    | not null
radius        | real                     | 4    | not null default 0
confidence    | real                     | 4+4  | not null default 5
parent_id     | bigint                   | 8    |

如果我沒記錯的話,我應該每行保存 66 個字節(138 是原始行,72 是新行)。然而這並沒有發生:這些表中有 7604913,原始表的大小為 1020 MB。新表的大小為 1159 MB。我曾經pg_size_pretty(pg_relation_size('<tablename>'))測量過尺寸。那麼我錯過了什麼?

注意:除了最後四列之外的所有列都是從另一個表繼承的(我當然也必須更改其中的佈局)。

**更新:**按照 Erwin Brandstetter 的建議執行後VACUUM FULL,新表只需要 734 MB。

物理表的大小通常不會通過執行VACUUM(或) 減小(除了從表末尾的可移動頁面的機會性修剪之外VACUUM ANALYZE)。您需要執行VACUUM FULL才能真正縮小表格。

如果您的桌子上有寫負載,那不一定是您想要定期做的事情。死行為 UPDATE 提供了擺動空間,以便將更新的行版本放置在同一數據頁上,從而獲得更好的性能。收縮和增長關係的物理表也是有代價的。另外,在表上VACUUM FULL取出一個排他鎖

這就是為什麼 autovacuum 只執行VACUUM(和ANALYZE)不執行VACUUM FULL

不過,最好將只讀(或大部分讀取)表保持在最小大小。更改表定義(或出於其他原因)後的過度膨脹也最好立即刪除。

嘗試VACUUM FULL兩個版本的表格並再次測量。應該顯示差異。

您還可以通過多個測試嘗試我的查詢,以獲取有關行/表大小的更多資訊。

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