PostgreSQL“ CLUSTER表名使用索引名;”占用的磁盘空间多于表大小加上所有索引的总和

问题描述

我在数据库中有一个很大的表。表的大小及其索引如下表所示:

 table_size 
----------------
 22 GB

 schemaname | scan_count | tablename |  indexname  | index_size 
------------+------------+-----------+-----------------------------------------------------------------+------------
 public     | 1352665306 | t1        | ind1        | 6686 MB
 public     | 1492127808 | t1        | ind2        | 6587 MB
 public     |    3492322 | t1        | ind3        | 4747 MB
 public     |   71810172 | t1        | ind4        | 4237 MB
 public     |   80547954 | t1        | cluster_ind | 4035 MB
 public     |    3628773 | t1        | ind6        | 3700 MB

如您所见,表大小为22GB。它有6个不同的索引,总共需要30GB的空间。

根据postgresql docs

CLUSTER可以使用对指定索引的索引扫描或(如果索引是b树)(如果索引是b树)对表进行重新排序,然后进行排序。它将尝试根据计划者的成本参数和可用的统计信息来选择更快的方法

使用索引扫描时,将创建表的临时副本,该副本包含按索引顺序排列的表数据。还将创建表上每个索引的临时副本。因此, 您在磁盘上需要的可用空间至少等于表大小和索引大小之和

但是,df -h显示包含Postgresql数据的分区上有75GB的可用空间,当我尝试使用cluster_ind索引对表进行群集时,我仍然用完磁盘空间下面的命令:

cluster table using cluster_ind;

我遇到这个错误

ERROR:  Could not extend file "base/16385/2165933.3": wrote only 4096 of 8192 bytes at block 394731
HINT:  Check free disk space.

问题:在群集期间,除了表大小及其索引大小总和以外,还在使用磁盘空间吗?以及如何估算使用索引在表上运行CLUSTER命令所需的空间?

解决方法

那可能是TOAST表。

使用class ArticleCrudController extends AbstractCrudController 来获取表格的完整大小。