Postgresql

在 VACUUM FULL (postgres) 之前檢查空間可用性

  • March 29, 2019

在大表上執行 VACUUM FULL之前,是否可以檢查表空間中有多少可重用空間?

我有一個大的 postgres 表(大約 20G),偶爾會出現 VACUUM FULL。該驅動器上的可用空間在 15-25 GB 之間變化。在嘗試每次清理之前,我會記錄表大小(使用 postgres 查詢)和可用磁碟空間(使用 OS 工具)。

我知道 VACUUM FULL 需要製作表格的完整副本。因此,如果表是 20G,則需要 20G 的可用空間。

有時表是 20G,只有 15G 的作業系統空間可用,而 Vacuum 可以工作。我猜需要的額外 5G 是從表空間內部恢復的。

其他時候由於空間不足,真空會失敗,我猜在這些情況下,在表空間中找不到所需的額外 5G。

我希望能夠事先檢查我是否有足夠的空間容納 VACUUM FULL,我該怎麼做?我知道表有多大,我知道作業系統有多少可用空間,但我不知道表空間中有多少可回收空間。

首先,我建議使用pgstattuple來獲取元組級別的統計資訊。

pgstattuple返回關係的物理長度、“死”元組的百分比和其他資訊。這可以幫助使用者確定是否 需要真空

例如

create extension pgstattuple ;
create table my_table ( id int , name text);
insert into my_table select a, md5(a::text) from generate_series(1, 1e7)a;

-- size of my_table
Schema |   Name   | Type  |  Owner   |  Size  | Description
--------+----------+-------+----------+--------+-------------
public | my_table | table | postgres | 651 MB |

-- dead_tuple_percent = 0, pgstattuple will not lock your table
SELECT tuple_percent, dead_tuple_count, dead_tuple_percent, free_space, free_percent FROM pgstattuple('my_table');

tuple_percent | dead_tuple_count | dead_tuple_percent | free_space | free_percent
---------------+------------------+--------------------+------------+--------------
        89.35 |                0 |                  0 |     338776 |         0.05

-- let update 50% rows
update my_table set name = name || id where id < 5000000;

-- now, dead_tuple_percent = 28.63%
tuple_percent | dead_tuple_count | dead_tuple_percent | free_space | free_percent
---------------+------------------+--------------------+------------+--------------
        60.43 |          4999999 |              28.63 |    1834236 |         0.17

-- size of my_table has increased

Schema |   Name   | Type  |  Owner   |  Size   | Description
--------+----------+-------+----------+---------+-------------
public | my_table | table | postgres | 1016 MB |                

-- try to vacuum full
vacuum full my_table;

-- after that, dead_tuple_percent = 0 and size of my_table has reduced
tuple_percent | dead_tuple_count | dead_tuple_percent | free_space | free_percent
---------------+------------------+--------------------+------------+--------------
        88.92 |                0 |                  0 |    1664780 |         0.23
Schema |   Name   | Type  |  Owner   |    Size    | Description
--------+----------+-------+----------+------------+-------------
public | my_table | table | postgres | 691 MB     |

其次,如果您在生產環境中,我建議您使用pg_repack來回收磁碟而不鎖定您的表。

pg_repack 是一個 PostgreSQL 擴展,可讓您從表和索引中刪除膨脹,並可選擇恢復聚集索引的物理順序。與 CLUSTER 和 VACUUM FULL 不同,它線上工作,在處理過程中不會對已處理的表持有獨占鎖。pg_repack 啟動效率很高,性能與直接使用 CLUSTER 相當。

例如:

/usr/pgsql-11/bin/pg_repack -d postgres -U postgres -n -t my_table  &

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