【问题标题】:Migrate PostgreSQL text/bytea column to large object?将 PostgreSQL text/bytea 列迁移到大对象?
【发布时间】:2019-03-06 03:12:43
【问题描述】:

我有一个表(10k 行),它在text 列中存储大值。当前最大的是 417 MB 未压缩(85 MB 烘烤)。这种设计的缺陷是无法将这些值流式传输(例如通过 JDBC) - 使用此列的任何内容都必须将整个内容读入内存。

是否有任何工具或快捷方式可用于将此列迁移到大型对象?最小化所需的工作磁盘和内存。

如果有什么不同,我将使用lo_compat_privileges

【问题讨论】:

标签: postgresql blob psql jdbc-postgres


【解决方案1】:

为什么不直接使用lo_from_bytea

例子:

SELECT 'test'::text::bytea;
   bytea    
------------
 \x74657374
(1 row)

SELECT lo_from_bytea(0, 'test'::text::bytea);
 lo_from_bytea 
---------------
        274052
(1 row)

SELECT lo_get(274052);
   lo_get   
------------
 \x74657374
(1 row)

因此,要将数据从文本实际移动(最好有备份)到 OID,您可以执行以下操作:

ALTER TABLE mytable ADD COLUMN value_lo OID;
UPDATE mytable SET value_lo = lo_from_bytea(0, value::bytea), value = NULL;
ALTER TABLE mytable DROP COLUMN value;
ALTER TABLE mytable RENAME COLUMN value_lo TO value;

...最后,由于 PostgreSQL 是一个 MVCC 数据库并且不会立即删除所有数据,您应该使用 VACUUM FULLCLUSTER 进行清理。

【讨论】:

  • Errh.. 没有。你不能弄乱 PostgreSQL 中的数据类型。我将更新答案以包含潜在的升级过程。
  • 好的,所以(假设大对象也被压缩)我需要两倍的当前表空间。但是这个单一的 UPDATE 是否会一次需要整个未压缩表的 WAL 空间?
  • 当然,每个写入活动都是出于安全原因。就个人而言,我什至从未想过将如此大的对象放入数据库中。通常,将数据存储在文件系统中并在数据库中保存文件路径引用就足够了,除非您需要将数据作为事务的一部分进行操作并且整个系统都需要是 ACID。在决定数据库设计之前,您是否阅读过 WIKI 页面? wiki.postgresql.org/wiki/BinaryFilesInDB
  • 是的,我需要对该表的单行进行跨国更新。但是,我不需要在单个事务中完成整个迁移。这就是为什么我要询问内存和磁盘使用情况。我没有 500GB 的 RAM,也没有无限的磁盘空间。
  • 好吧,由于 PostgreSQL 基本上是写时复制工作,并且数据库中有如此大的对象,您必须为并发写入和维护操作考虑相当多的备用容量 (HDD/SSD)作为这些模式演变的步骤。为此,您不需要太多 RAM。并且您始终可以使用附加的 WHERE 子句(甚至在开始时一个接一个)小批量启动 UPDATE 语句,以了解性能并预测总运行时间。但是很抱歉,如果不复制实际数据,就无法进行就地转换。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-03-08
  • 2019-10-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多