openGauss/MogDB数据库里bytea二进制类型受segment size编译参数限制,默认不能超过1GB,如果字段存储数据超过1GB可以使用lo(Large Object)扩展类型。
lo类型需要先创建lo extension
$ gsql -p5432 -Uomm postgres -r gsql ((MogDB 2.0.1 build f892ccb7) compiled at 2021-07-09 16:15:21 commit 0 last mr ) Non-SSL connection (SSL connection is recommended when requiring high-security) Type "help" for help. postgres=# create extension lo; CREATE EXTENSION
复制
创建完lo扩展,我们新建test_lo表,info字段使用lo类型。
postgres=# create table test_lo(id int,info lo); CREATE TABLE
复制
创建test_lo表管理触发器,对update和delete操作使用lo_manage函数管理,不然会产生孤立大对象。
postgres=# create trigger test_lo before UPDATE OR DELETE ON test_lo FOR EACH ROW EXECUTE procedure lo_manage(info); WARNING: Trigger function with non-plpgsql type is not recommended. DETAIL: Non-plpgsql trigger function are not shippable by default. HINT: Unshippable trigger may lead to bad performance. CREATE TRIGGER
复制
使用dd生成2GB文件
postgres=# \! dd if=/dev/zero of=test_lo bs=1M count=2048 && sync 记录了2048+0 的读入 记录了2048+0 的写出 2147483648字节(2.1 GB,2.0 GiB)已复制,0.805435 s,2.7 GB/s
复制
测试lo_import函数导入数据到数据表
postgres=# insert into test_lo values(1,lo_import('/home/omm/test_lo')); INSERT 0 1
复制
可以看到数据可以正常导入,如果不使用lo类型,使用bytea类型会提示下面的报错。
ERROR: requested length too large
复制
测试lo_export函数导出数据表数据到文件
postgres=# select lo_export(test_lo.info,'/home/omm/test_ext_lo') from test_lo where id=1; lo_export ----------- 1 (1 row)
复制
可以看到数据正常导出。
查看导入导出的数据文件,也可以使用diff命令进行比对。
postgres=# \! ls -lh test_* -rw-r--r-- 1 omm dbgrp 2.0G 12月 17 13:00 test_ext_lo -rw------- 1 omm dbgrp 2.0G 12月 17 12:58 test_lo
复制
查看数据表大对象字段大小
分两步进行,首先查大对象字段的oid(lo类型字段在用户表里面只存储一个oid引用指针,并不实际存数据)
postgres=# select * from test_lo; id | info ----+------- 1 | 16392 (1 row)
复制
实际数据使用多条bytea记录存储在pg_largeobject表,可以根据oid查询统计字段的大小
postgres=# select loid,pg_size_pretty(sum(octet_length(data))) from pg_largeobject where loid =16392 group by loid; loid | pg_size_pretty -------+---------------- 16392 | 2048 MB (1 row)
复制
也可以使用如下函数来查询
create or replace function get_lo_size(oid) returns bigint volatile strict as $function$ declare fd integer; sz bigint; begin fd := lo_open($1, x'40000'::int); perform lo_lseek64(fd, 0, 2); sz := lo_tell64(fd); perform lo_close(fd); return sz; end; $function$ language plpgsql;
复制
查询结果如下
postgres=# select pg_size_pretty(get_lo_size(16392)); pg_size_pretty ---------------- 2048 MB (1 row)
复制
再来测试JDBC应用层的使用
JDBC-Java文件入库
public static void main(String[] args) throws Exception{ Class.forName("org.postgresql.Driver"); Connection conn = DriverManager.getConnection("jdbc:postgresql://ip:port/dbname","username","password"); conn.setAutoCommit(false); LargeObjectManager lobj = conn.unwrap(org.postgresql.PGConnection.class).getLargeObjectAPI(); long oid = lobj.createLO(LargeObjectManager.READ | LargeObjectManager.WRITE); LargeObject obj = lobj.open(oid, LargeObjectManager.WRITE); File file = new File("c:/work/test_lo"); FileInputStream fis = new FileInputStream(file); byte buf[] = new byte[10*1024*1024]; int s, tl = 0; while ((s = fis.read(buf, 0, 2048)) > 0) { obj.write(buf, 0, s); tl += s; } obj.close(); PreparedStatement ps = conn.prepareStatement("INSERT INTO test_lo VALUES (?, ?)"); ps.setInt(1, 100); ps.setLong(2, oid); ps.executeUpdate(); ps.close(); fis.close(); conn.commit(); conn.close(); }
复制
JDBC-Java读数据输出到文件
public static void main(String[] args) throws Exception{ Class.forName("org.postgresql.Driver"); Connection conn = DriverManager.getConnection("jdbc:postgresql://ip:port/dbname","username","password"); conn.setAutoCommit(false); LargeObjectManager lobj = conn.unwrap(org.postgresql.PGConnection.class).getLargeObjectAPI(); PreparedStatement ps = conn.prepareStatement("SELECT info FROM test_lo WHERE id = ?"); ps.setInt(1, 100); ResultSet rs = ps.executeQuery(); File file = new File("c:/work/test_out_lo"); FileOutputStream fos = new FileOutputStream(file); while (rs.next()) { long oid = rs.getLong(1); LargeObject obj = lobj.open(oid, LargeObjectManager.READ); byte buf[] = new byte[10*1024*1024]; int s, tl = 0; while ((s = obj.read(buf, 0, 2048)) > 0) { fos.write(buf, 0, s); tl += s; } obj.close(); } rs.close(); ps.close(); fos.close(); conn.commit(); conn.close(); }
复制
最后修改时间:2022-10-22 12:48:02
「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。
评论
openGauss3.0里,这些个功能是被屏蔽的。。。
2年前

评论
您好,您的文章已入选合格奖,10墨值奖励已经到账请查收!
❤️我们还会实时派发您的流量收益。
3年前

评论
相关阅读
openGauss荣获中国软件行业协会多奖项,技术升级再创行业新高度
openGauss
546次阅读
2025-04-30 14:30:58
MogDB 发布更新,解决 openGauss 数据库在长事务情况下Ustore表膨胀问题
MogDB
307次阅读
2025-04-17 10:41:41
MogDB 发布更新,解决 openGauss 数据库在长事务情况下Ustore表膨胀问题
云和恩墨
201次阅读
2025-04-16 09:52:02
GitCode 成 openGauss 新归宿,国产开源数据库里程碑事件
严少安
171次阅读
2025-04-27 11:37:53
荣誉时刻!openGauss认证证书快递已发,快来看看谁榜上有名!
墨天轮小教习
162次阅读
2025-04-23 17:39:13
单个执行机并行执行MySQL到openGauss数据迁移子任务
Clipnosis
146次阅读
2025-04-30 16:39:58
openGauss6.0.0适配操作系统自带的软件,不依赖三方库
来杯拿铁
95次阅读
2025-04-18 10:49:53
Postgresql数据库单个Page最多存储多少行数据
maozicb
90次阅读
2025-04-23 16:02:19
openGauss新特性 | openGauss-DataVec向量数据库特性介绍
openGauss
64次阅读
2025-04-17 10:41:47
RISC-V 首迎 openGauss 7.0.0-RC1 全量版适配!数据库核心功能完整落地开源架构
openGauss
49次阅读
2025-04-16 10:33:59