我有一个包含jsonb列的表,结果是每行在该列中存储大量json数据会占用太多空间,该表大约消耗了9000万条记录,大约167 GB的存储空间.

现在,我想从数据库中删除该列并回收存储空间.我从PSQL文档here中了解了Vacuum的概念.从文档中我了解到,Postgres自动运行例行的真空作业(job),根据文档中提到的标准定期回收存储.

我对这句话有些困惑:

普通吸尘器(没有装满)只是回收空间,使其可重复使用.这种形式的命令可以与表的正常读写并行操作,因为没有获得独占锁.然而,额外的空间不会返回给操作系统(在大多数情况下);它只是在同一个表中保持可用以供重用.

我在这里没有什么疑问,从我读到的文档中完全真空需要额外的空间,现在由于我的数据库没有这样的空间可用,想要确保自动真空也有同样的要求吗?在应用这些更改(删除列)之前,我是否需要升级空间?有没有办法在当地验证这一点?

推荐答案

如果要重用同一张表主要需要驱动器空间,只需删除列并删除vacuum张表(不包括full),或者将其留到自动吸尘器中,仅此而已.

既然我的数据库没有那种可用的空间,想确保自动吸尘器也有同样的要求吗

除非您采取额外的步骤来禁用自动吸尘器,否则它一直在您的服务器上运行:pg_stat_all_tables系统视图可以告诉您最近发生的时间.查看服务器日志(log)以判断它报告的故障.你可以在pg_stat_progress_vacuum中看到它的进展.

正如您引用的文档中所概述的,Regular vacuum只为同一个表回收空间(除非它在最后释放整个页面),因此您通常不会看到与使用vacuum full时一样多的总空间消耗下降.它执行就地的内部表清理,目的是保持其大小,而不试图压缩它.

如果您对表大小的估计值是pg_total_relation_size(),那么不仅在表页中/从表页中,而且在表页的TOAST和索引中都有可以回收的空间.

索引是相关的,但又是独立的对象,因此它们占用的空间将被释放.如果您对这一列有索引,您将能够回收它使用的整个空间.将该列与其他一些列一起使用的索引将不得不删除并重新定义,这也意味着由于重写时的压缩以及整体较轻的 struct ,这也意味着一些额外的可用空间-只要您有空间来执行它.如果不这样做,则可以在删除索引定义之前将其保存:

create temp table index_definitions as select indexdef 
  from pg_indexes where schemaname='your_schema' and tablename='your_table';

一旦你有了空间,重新构建它们(在编辑掉你要删除的列之后)

do $p$ declare indexdef_ text; 
begin for indexdef_ in select indexdef from index_definitions loop
          execute indexdef_;
      end loop;
      drop table index_definitions;
end $p$;

默认情况下,所有vacuum都与PROCESS_TOAST=true一起运行,因此您的 cogo toast 也可以缩小.当你在体重下降后考虑vacuum full,你可以考虑通过设置PROCESS_TOAST=false来完全清理主桌,或者通过从系统pg_class中挑选 cogo toast 来完全清理主桌:

select reltoastrelid::regclass,  pg_size_pretty(pg_relation_size(reltoastrelid)) 
from pg_class
where reltoastrelid<>0 and 'r'=relkind
and (oid::regclass)::text='your_schema.your_table';

如果/当你做vacuum full的时候,你可以跟踪它在pg_stat_progress_cluster的进度.你也可以用verbose来运行它.


在应用这些更改(删除列)之前,我是否需要升级空间?

你不需要.alter table...drop column本身不会导致重写,所以它不需要空间.随后的自动吸尘器不会try 重写,因此也不需要它.


有办法在本地验证吗?

您可以设置该系统的镜像,通过pg_dump|psql复制该表,使用虚拟记录填充其他表,以便您也有完全相同的剩余空间量,并在那里运行测试.将表格重写到另一个系统将使其紧凑,因此这并不完全是苹果对苹果的比较,但这是一个安全的测试场地.

Database相关问答推荐

为什么Hibernate会为@JoinTable的双向@OneToMany关系生成一个复杂的子查询?

Active Record - 获取数据库中的第二个、第三个.. 项(无 ID)

如何在 ubuntu 中使用脚本添加带有连字符的数据库名称

实体关系图. IS A 关系如何转换为table表?

函数到关系映射比对象到关系更容易吗?

Oracle SQL 开发人员中的 DB2 数据库

按纬度/经度进行半径搜索

使用 2 个进程处理数据库

无法启动 MongoDB:Windows 中的系统错误 1067

与号 (&) 处的 XML 错误

我可以在没有数据源的情况下配置 Grails 吗?

行之间的 SQL 差异

对于 Postgres (Windows),有没有像 TOAD 一样好的东西?

我应该在数据库模式中允许空值吗?

MySQL 中 NOW()、SYSDATE() 和 CURRENT_DATE() 之间的区别

显式事务回滚是否必要?

Python中准备好的语句和参数化查询之间的混淆

关系未更新的 NSFetchedResultsController

多币种 - 存储什么以及何时转换?

我将如何为读写操作实现单独的数据库?