VACUUM FULL 和 CLUSTER 的 PostgreSQL 区别

Aru*_*n P 17 postgresql clustered-index vacuum postgresql-9.1

我有一个表,其中数据占用 200 GB 大小,其上的 6 个索引占用 180 GB 大小。它膨胀了 30%,所以我想回收它占用的不需要的空间。它聚集在job_id_idx 索引上。

那么要回收空间我需要使用cluster命令还是vacuum full命令?

  1. 这两个命令有什么区别?

  2. vacuum full为了通过一些列相同cluster的命令?

  3. 两个命令中是否都重新创建了索引?

  4. 在我的情况下,哪一个会更快?

PostgreSQL 数据库版本为 9.1

dez*_*zso 11

为了检查是什么CLUSTER,我从早期的实验中取出了一张表格,其中基本上包含了前 1000 万个正整数。我已经删除了一些行,还有另一列,但这些只影响实际的表大小,所以它不是那么有趣。

首先,VACUUM FULL在桌子上跑步后fka,我测量了它的大小:

\dt+ fka
                    List of relations
 Schema | Name | Type  |  Owner   |  Size  | Description 
--------+------+-------+----------+--------+-------------
 public | fka  | table | test     | 338 MB | 
Run Code Online (Sandbox Code Playgroud)

然后让我们从表的最开始看数据的物理顺序:

SELECT *, ctid FROM fka ORDER BY ctid LIMIT 5;

 id  | col1 |  ctid   
-----+------+---------
   2 | 2    | (0,1)
   3 | 3    | (0,2)
   4 | 4    | (0,3)
   5 | 5    | (0,4)
   6 | 6    | (0,5)
Run Code Online (Sandbox Code Playgroud)

现在让我们删除一些行:

DELETE FROM fka WHERE id % 10 = 5;
--DELETE 1000000
Run Code Online (Sandbox Code Playgroud)

在此之后,报告的表大小没有改变。那么现在让我们看看有什么CLUSTER作用:

CLUSTER fka USING fka_pkey;

SELECT *, ctid FROM fka ORDER BY ctid LIMIT 5;

 id  | col1 |  ctid   
-----+------+---------
   2 | 2    | (0,1)
   3 | 3    | (0,2)
   4 | 4    | (0,3)
   6 | 6    | (0,4)
   7 | 7    | (0,5)
Run Code Online (Sandbox Code Playgroud)

操作后,表大小从 338 MB 更改为 296 MB。从ctid描述元组在页面中的物理位置的列中,您还可以看到行匹配id = 5以前所在的位置没有间隙。

当元组被重新排序时,应该重新创建索引,以便它们指向正确的位置。

因此,不同之处似乎在于VACUUM FULL不对行进行排序。据我所知,这两个命令使用的机制存在一些差异,但从实用的角度来看,这似乎是主要的(唯一的?)差异。


cpt*_*tPH 9

VACUUM FULL将表的全部内容重写到一个没有额外空间的新磁盘文件中,允许将未使用的空间返回给操作系统。此方法还需要额外的磁盘空间,因为它会写入表的新副本,并且在操作完成之前不会释放旧副本。通常这应该只在需要从表中回收大量空间时使用。

http://www.postgresql.org/docs/9.1/static/sql-vacuum.html

CLUSTER指示 PostgreSQL 根据 index_name 指定的索引对 table_name 指定的表进行集群。索引必须已经在 table_name 上定义。当表被聚簇时,它会根据索引信息进行物理重新排序,并在其上获取 ACCESS EXCLUSIVE 锁。

http://www.postgresql.org/docs/9.1/static/sql-cluster.html

同样有趣:is-a-reindex-required-after-cluster

但也许您所需要的只是一个简单的方法REINDEX,它使用存储在索引表中的数据重建索引,替换索引的旧副本。

http://www.postgresql.org/docs/9.1/static/sql-reindex.html