PostgreSQL中的大对象

我们知道在 Oracle 数据库中,大对象有三种类型,分别是 CLOB,BLOB 和 BFILE。在 Oracle 数据库中大对象最大存储根据配置可以达到 8TB 到 128TB。然而在 PostgreSQL 数据库中并没有提供这三种数据类型。因此在进行迁移的时候,我们需要做类型的映射。我们可以将 CLOB 和 BLOB 分别映射到 text 和 bytea 数据类型上。此外,PostgreSQL 的插件 pg_largeobject 也提供了一种大对象的支持。

text & bytea

CLOB 和 BLOB 分别用于存储字符大对象和二进制大对象,这与 PostgreSQL 中的 text 和 bytea 很类似,因此在迁移 Oracle 数据库的时候也就将他们分别对应起来。

pg_largeobject

pg_largeobject 是 PostgreSQL 插件提供的一个大对象解决方案。在 pg_largeobject 中,所有的大对象都存储在系统表 pg_largeobject 中;此外,每个大对象在系统表 pg_largeobject_metadata 中也会有一条记录大对象的相关元信息,他们的定义如下所示:

1postgres=# \d pg_largeobject 2Table "pg_catalog.pg_largeobject" 3Column | Type | Collation | Nullable | Default 4--------+---------+-----------+----------+--------- 5loid | oid | | not null | 6pageno | integer | | not null | 7data | bytea | | not null | 8Indexes: 9"pg_largeobject_loid_pn_index" UNIQUE, btree (loid, pageno)
1postgres=# \d pg_largeobject_metadata 2Table "pg_catalog.pg_largeobject_metadata" 3Column | Type | Collation | Nullable | Default 4----------+-----------+-----------+----------+--------- 5oid | oid | | not null | 6lomowner | oid | | not null | 7lomacl | aclitem[] | | | 8Indexes: 9 "pg_largeobject_metadata_oid_index" UNIQUE, btree (oid)

采用 pg_largeobject 所存储的大对象最大可以达到 4TB 的存储空间,并且支持随机读写。pg_largeobject 采用 OID 的方式来引用 pg_largeobject 表中的大对象。例如,我们创建一个表来存储图片数据,如下所示:

1CREATE TABLE image(name text, raster oid);

pg_largeobject 提供了一系列函数用于创建、导入和导出大对象,见官方文档服务端函数。下面是简单的大对象插入导出的测试输出:

1postgres=# INSERT INTO image VALUES('image1', lo_import('/tmp/screenshot.png')); 2INSERT 0 1 3postgres=# SELECT loid, COUNT(page no) FROM pg_largeobject GROUP BY loid; 4 loid | count 5-------+------- 6 24598 | 25 7(1 row) 8 9postgres=# SELECT raster, lo_export(raster, '/tmp/screenshot-e.png') FROM image WHERE name = 'image1'; 10 raster | lo_export 11--------+----------- 12 24598 | 1 13(1 row) 14 15postgres=# \! md5sum /tmp/screenshot.png /tmp/screenshot-e.png 16dc51d60215f547a897d4d73beba65ded /tmp/screenshot.png 17dc51d60215f547a897d4d73beba65ded /tmp/screenshot-e.png

需要注意的是,在使用 pg_largeobject 来管理大对象时,我们需要额外的操作来管理大对象。例如,上面的示例中,如果我们想要删除表 image 中名称为 image1 的记录,我们还需在 pg_largeobject 中删除 loid = 24598 的记录。如下所示:

1postgres=# DELETE FROM image WHERE name = 'image1'; 2DELETE 1 3postgres=# SELECT name FROM image; 4 name 5------ 6(0 rows) 7 8postgres=# SELECT loid, COUNT(pageno) FROM pg_largeobject GROUP BY loid; 9 loid | count 10-------+------- 11 24598 | 25 12(1 row) 13 14postgres=# DELETE FROM pg_largeobject WHERE loid = 24598; 15DELETE 25 16postgres=# SELECT loid, COUNT(pageno) FROM pg_largeobject GROUP BY loid; 17 loid | count 18------+------- 19(0 rows)

通常,我们会创建一个触发器来进行 OID 的删除。此外,pg_largeobject 提供了 lo_put 和 lo_get 函数来随机读写大对象。需要注意的是,我们在使用 libpq 对大对象进行读写时必须在事务中。

为什么对大对象进行读写时必须在事务中

pg 数据库对于大对象类型的资源进行操作时,必须保证所有的大对象操作函数在同一个SQL事务块中发生,因为大对象类型的文件描述符仅在事务的持续时间内有效

All large object manipulation using these functions must take place within an SQL transaction block, since large object file descriptors are only valid for the duration of a transaction.

PostgreSQL: Documentation: 15: 35.3. Client Interfaces

点赞
收藏

评论区

加载中...

相关推荐

MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1

文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

MySQL部分从库上面因为大量的临时表tmp_table造成慢查询

背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_

PPDB:今晚老齐直播

【今晚老齐直播】今晚(本周三晚)20:0021:00小白开始“用”飞桨(https://www.oschina.net/action/visit/ad?id1185)由PPDE(飞桨(https://www.oschina.net/action/visit/ad?id1185)开发者专家计划)成员老齐,为深度学习小白指点迷津。

VBox 启动虚拟机失败

在Vbox(5.0.8版本)启动Ubuntu的虚拟机时,遇到错误信息:NtCreateFile(\\Device\\VBoxDrvStub)failed:0xc000000034STATUS\_OBJECT\_NAME\_NOT\_FOUND(0retries) (rc101)Makesurethekern

FLV文件格式

1.        FLV文件对齐方式FLV文件以大端对齐方式存放多字节整型。如存放数字无符号16位的数字300(0x012C),那么在FLV文件中存放的顺序是:|0x01|0x2C|。如果是无符号32位数字300(0x0000012C),那么在FLV文件中的存放顺序是:|0x00|0x00|0x00|0x01|0x2C。2.