当前位置: 首页 > news >正文

PostgreSQL 大对象管理指南:pg_largeobject 从原理到实践

概述

有时候,你可能需要在 PostgreSQL 中管理大对象,例如 CLOB、BLOB 和 BFILE。PostgreSQL 中有两种处理大对象的方法:一种是使用现有的数据类型,例如用于二进制大对象的 bytea 和用于基于字符的大对象的 text;另一种是使用 pg_largeobject。本文将解释如何使用 pg_largeobject。

pg_largeobject

pg_largeobject 是 PostgreSQL 提供的大对象解决方案之一,它允许以流式方式访问存储在特殊大对象结构中的用户数据。当处理的数据值过大而无法作为一个整体方便地操作时,流式访问非常有用。

pg_largeobject 是一个用于存储实际大对象的系统表。每个大对象在系统表 pg_largeobject_metadata 中都有一个条目。使用 pg_largeobject 管理的大对象可以通过读/写 API 进行创建、修改和删除。pg_largeobject 允许存储高达 4TB 的大对象。

另一种大对象解决方案是使用现有的数据类型 bytea 和 text,它们基于 TOAST 表构建,限制了大对象的大小为 1GB。

以下是为 pg_largeobject 设计的两个系统表的架构。

postgres=# \d+ pg_largeobject;Table "pg_catalog.pg_largeobject"Column |  Type   | Collation | Nullable | Default | Storage  | Compression | Stats target | Description
--------+---------+-----------+----------+---------+----------+-------------+--------------+-------------loid   | oid     |           | not null |         | plain    |             |              |pageno | integer |           | not null |         | plain    |             |              |data   | bytea   |           | not null |         | extended |             |              |
Indexes:"pg_largeobject_loid_pn_index" PRIMARY KEY, btree (loid, pageno)
Access method: heappostgres=# \d+ pg_largeobject_metadata;Table "pg_catalog.pg_largeobject_metadata"Column  |   Type    | Collation | Nullable | Default | Storage  | Compression | Stats target | Description
----------+-----------+-----------+----------+---------+----------+-------------+--------------+-------------oid      | oid       |           | not null |         | plain    |             |              |lomowner | oid       |           | not null |         | plain    |             |              |lomacl   | aclitem[] |           |          |         | extended |             |              |
Indexes:"pg_largeobject_metadata_oid_index" PRIMARY KEY, btree (oid)
Access method: heap

pg_largeobject 接口

PostgreSQL 通过 libpq 库提供客户端接口来访问大对象。该接口类似于 Unix 文件系统接口,例如 create、open、read、write、lseek 等。

注意,使用该接口操作大对象时,必须在 SQL 事务块内进行,因为大对象文件描述符仅在特定事务中有效。以下是与 pg_largeobject 相关的所有接口。

postgres=# \dfS lo*List of functionsSchema   |     Name      | Result data type |    Argument data types    | Type
------------+---------------+------------------+---------------------------+------pg_catalog | lo_close      | integer          | integer                   | funcpg_catalog | lo_creat      | oid              | integer                   | funcpg_catalog | lo_create     | oid              | oid                       | funcpg_catalog | lo_export     | integer          | oid, text                 | funcpg_catalog | lo_from_bytea | oid              | oid, bytea                | funcpg_catalog | lo_get        | bytea            | oid                       | funcpg_catalog | lo_get        | bytea            | oid, bigint, integer      | funcpg_catalog | lo_import     | oid              | text                      | funcpg_catalog | lo_import     | oid              | text, oid                 | funcpg_catalog | lo_lseek      | integer          | integer, integer, integer | funcpg_catalog | lo_lseek64    | bigint           | integer, bigint, integer  | funcpg_catalog | lo_open       | integer          | oid, integer              | funcpg_catalog | lo_put        | void             | oid, bigint, bytea        | funcpg_catalog | lo_tell       | integer          | integer                   | funcpg_catalog | lo_tell64     | bigint           | integer                   | funcpg_catalog | lo_truncate   | integer          | integer, integer          | funcpg_catalog | lo_truncate64 | integer          | integer, bigint           | funcpg_catalog | lo_unlink     | integer          | oid                       | funcpg_catalog | log           | double precision | double precision          | funcpg_catalog | log           | numeric          | numeric                   | funcpg_catalog | log           | numeric          | numeric, numeric          | funcpg_catalog | log10         | double precision | double precision          | funcpg_catalog | log10         | numeric          | numeric                   | funcpg_catalog | loread        | bytea            | integer, integer          | funcpg_catalog | lower         | anyelement       | anymultirange             | funcpg_catalog | lower         | anyelement       | anyrange                  | funcpg_catalog | lower         | text             | text                      | funcpg_catalog | lower_inc     | boolean          | anymultirange             | funcpg_catalog | lower_inc     | boolean          | anyrange                  | funcpg_catalog | lower_inf     | boolean          | anymultirange             | funcpg_catalog | lower_inf     | boolean          | anyrange                  | funcpg_catalog | lowrite       | integer          | integer, bytea            | func

4. 示例

为了更好地理解如何使用 pg_largeobject,以下是一些示例。

创建一个大对象

postgres=# select lo_create(0);lo_create
-----------16384
(1 row)postgres=# select * from pg_largeobject_metadata;oid  | lomowner | lomacl
-------+----------+--------16384 |       10 |
(1 row)postgres=# select * from pg_largeobject;loid | pageno | data
------+--------+------
(0 rows)

导入一个大对象

创建一个简单的文本文件。

$ echo "this is a test on pg_largeobject." > /tmp/lo_test.txt

将文本文件导入 pg_largeobject。

postgres=*# select lo_import('/tmp/lo_test.txt');lo_import
-----------16385
(1 row)postgres=# select * from pg_largeobject_metadata;oid  | lomowner | lomacl
-------+----------+--------16384 |       10 |16385 |       10 |
(2 rows)

显示导入 pg_largeobject 后的内容。

postgres=# set bytea_output = 'escape';
SET
postgres=# select * from pg_largeobject;loid  | pageno |                 data
-------+--------+---------------------------------------16385 |      0 | this is a test on pg_largeobject.\012
(1 row)

操作一个大对象

使用 pg_largeobject 的一大优势是它允许我们修改大对象。以下是一个向另一个大对象追加信息的示例。

begin;
select lo_open(16385, x'60000'::int);
select lo_lseek(0, 32, 0);
select lowrite(0, ', + large object.\012');
commit;postgres=# select * from pg_largeobject;loid  | pageno |                         data
-------+--------+-------------------------------------------------------16385 |      0 | this is a test on pg_largeobject, + large object.\012
(1 row)

这里,x’60000’用于将大对象访问模式设置为INV_WRITE|INV_READ。这些访问模式在头文件 libpq/libpq-fs.h 中定义如下。

#define INV_WRITE               0x00020000
#define INV_READ                0x00040000

将大对象导出到外部文件

除了在 PostgreSQL 内部访问大对象外,你还可以将大对象导出到外部文件。

postgres=# select lo_export(16385, '/tmp/lo_test_new.txt');

然后,你可以像普通文件一样检查内容。

$ cat /tmp/lo_test_new.txt
this is a test on pg_largeobject, + large object.

将操作封装到函数中

你可以使用 libpq 库构建函数来自定义大对象的访问。以下是一个使用 PL/SQL 的简单示例。

DROP FUNCTION IF EXISTS my_lo_append;
CREATE OR REPLACE FUNCTION my_lo_append(oid, bytea)
RETURNS oid AS $$
DECLAREfd integer;bytes integer;
BEGINfd := lo_open($1, x'60000'::int);bytes := lo_lseek(0, 0, 2);bytes := lowrite(fd, $2);PERFORM lo_close(fd);RETURN $1;
END;
$$ LANGUAGE plpgsql STRICT;

然后调用自定义函数来追加一些信息。

postgres=# select my_lo_append(16385::oid, 'abc123'::bytea);my_lo_append
--------------16385
(1 row)postgres=# set bytea_output = 'escape';
SETpostgres=# select * from pg_largeobject;loid  | pageno |                    data
-------+--------+---------------------------------------------16385 |      0 | this is a test on pg_largeobject.\012abc123
(1 row)postgres=# select lo_export(16385, '/tmp/lo_test_new.txt');lo_export
-----------1
(1 row)

你还可以检查导出后作为文件操作的大对象。

$ cat /tmp/lo_test_new.txt
this is a test on pg_largeobject.
abc123

总结

在本文中,我解释了如何使用 pg_largeobject 来处理 PostgreSQL 中的大对象,并提供了一些非常简单的示例。希望这能有所帮助。


文章转载自:

http://hh2yyNyy.fnLnp.cn
http://iQKcjrmG.fnLnp.cn
http://WQiyWcRV.fnLnp.cn
http://yrD9xb10.fnLnp.cn
http://QF0KT3EF.fnLnp.cn
http://Kc3N4Nu4.fnLnp.cn
http://nYMJrWu4.fnLnp.cn
http://4H6NLp9C.fnLnp.cn
http://JbY95sXx.fnLnp.cn
http://PFqINbw8.fnLnp.cn
http://ILylac0L.fnLnp.cn
http://ELW5yqks.fnLnp.cn
http://FbyC8PJx.fnLnp.cn
http://VRqZw8Ub.fnLnp.cn
http://66HnOwjy.fnLnp.cn
http://hPbl5wwG.fnLnp.cn
http://LPI8bOGi.fnLnp.cn
http://T0clnqMJ.fnLnp.cn
http://lfHDXyoS.fnLnp.cn
http://NYicqVgf.fnLnp.cn
http://Vfmw3Fqe.fnLnp.cn
http://Nbp5ICLQ.fnLnp.cn
http://m3s26BMH.fnLnp.cn
http://OMMQiU1T.fnLnp.cn
http://jgI2a1pL.fnLnp.cn
http://3EJyCUWS.fnLnp.cn
http://jU6Xm0fW.fnLnp.cn
http://AiWBJq3P.fnLnp.cn
http://gzfat8mD.fnLnp.cn
http://14jqj9P3.fnLnp.cn
http://www.dtcms.com/a/375662.html

相关文章:

  • 传统项目管理的局限性有哪些
  • 内核函数:copy_process
  • 《UE5_C++多人TPS完整教程》学习笔记50 ——《P51 多人游戏中的俯仰角(Pitch in Multiplayer)》
  • RL【5】:Monte Carlo Learning
  • 深度解析HTTPS:从加密原理到SSL/TLS的演进之路
  • minio 文件批量下载
  • 【算法专题训练】19、哈希表
  • AJAX入门-URL、参数查询、案例查询
  • 安装ultralytics
  • Eino ChatModel 组件指南摘要
  • 腾讯codebuddy-cli重磅上线-国内首家支持全形态AI编程工具!
  • 基于PCL(Point Cloud Library)的点云高效处理方法
  • UVa1302/LA2417 Gnome Tetravex
  • STC Link1D电脑端口无法识别之升级固件
  • 【C++】LLVM-mingw + VSCode:Windows 开发攻略
  • SRM系统有哪些核心功能?企业该如何科学选型?
  • LINUX99 centos8:网络 yum配置;shell:while [ $i -ne 5 ];do let i++ done
  • 【陇剑杯2025】密码复现(部分)
  • 漫谈《数字图像处理》之图像自适应阈值处理
  • Melon: 基于marker基因的三代宏基因组分类和定量软件
  • 水题记录1.7
  • JVM 执行引擎详解!
  • lua中 string.match返回值
  • 2025-安装集成环境XAMPP
  • 整体设计 之 绪 思维导图引擎 :思维价值链分层评估的 思维引导和提示词导航 之 引 认知系统 之6之 序 认知元架构 之1(豆包助手 之3)
  • 【教学类-07-10】20250909中3班破译电话号码(手写数字版、撕贴版、头像剪贴底纹版、抄写填空版)
  • 【初阶数据结构】算法复杂度
  • PowerBI 的双隐藏,我在QuickBI 里也找到了
  • AI赋能训诂学:解码古籍智能新纪元
  • 微服务雪崩问题与系统性防御方案