PostgreSQL的大对象以及空间使用 (3)
2020-10-12 08:58 abce 阅读(583) 评论(1) 编辑 收藏 举报
在上一篇文章中,我们已经看到大对象被分成每个元组,每个元组包含2048个字节,每个chunk的行为与常规元组非常相似。
注意:在PostgreSQL中,借助TOAST技术,可以将大量数据与表一起存储。
大对象没有插入应用表中,但是以不同的方式受到威胁。使用大对象的应用常具有一个包含OID类型的列的表。当应用程序创建新的大对象时,将为其分配一个新的OID号,并将此号插入到应用表中。
现在,对于来自其他RDBMS(例如Oracle)的人来说,这是一个常见错误,认为当删除该行的引用,大对象会自动取消链接。事实并非如此,我们需要将其与应用明确断开链接(unlink)。
1 2 3 4 5 6 7 8 9 10 11 12 13 | lob_test=# vacuum full pg_largeobject; VACUUM lob_test=# select count (*) from pg_largeobject_metadata; count ------- 0 (1 row) lob_test=# select pg_relation_size( 'pg_largeobject' )/8192 as pages; pages ------- 0 (1 row) |
让我们插入一个新的LOB并在表t中引用它:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | lob_test=# CREATE TABLE t (id integer , file oid); CREATE TABLE lob_test=# \lo_import /tmp/zeroes lo_import 16546 lob_test=# INSERT INTO t VALUES (1, 16546); INSERT 0 1 lob_test=# select generate_series as pageno, ( select count (*) from heap_page_items(get_raw_page( 'pg_largeobject' ,generate_series)) where t_infomask:: bit (16) & x '0800' :: bit (16) = x '0800' :: bit (16)) from generate_series(0,4); pageno | count --------+------- 0 | 107 1 | 107 2 | 107 3 | 107 4 | 84 |
另一个:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | lob_test=# \lo_import /tmp/zeroes lo_import 16547 lob_test=# INSERT INTO t VALUES (2, 16547); INSERT 0 1 lob_test=# select generate_series as pageno, ( select count (*) from heap_page_items(get_raw_page( 'pg_largeobject' ,generate_series)) where t_infomask:: bit (16) & x '0800' :: bit (16) = x '0800' :: bit (16)) from generate_series(0,9); pageno | count --------+------- 0 | 107 1 | 107 2 | 107 3 | 107 4 | 107 5 | 107 6 | 107 7 | 107 8 | 107 9 | 61 (10 rows ) lob_test=# select * from t; id | file ----+------- 1 | 16546 2 | 16547 (2 rows ) |
如果我们删除第一个,它的LOB块仍然存在,且有效:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | lob_test=# DELETE FROM t WHERE id=1; DELETE 1 lob_test=# select * from t; id | file ----+------- 2 | 16547 (1 row) lob_test=# select generate_series as pageno, ( select count (*) from heap_page_items(get_raw_page( 'pg_largeobject' ,generate_series)) where t_infomask:: bit (16) & x '0800' :: bit (16) = x '0800' :: bit (16)) from generate_series(0,9); pageno | count --------+------- 0 | 107 1 | 107 2 | 107 3 | 107 4 | 107 5 | 107 6 | 107 7 | 107 8 | 107 9 | 61 (10 rows ) |
如果我们想清理掉LOB,我们必须解除它的链接,要么显式地解除,要么在删除应用程序表中的一条记录时使用触发器解除LOB的链接。
它扫描pg_largeobject_metadata并搜索具有OID列的表,查找是否有对lob的引用。未被引用的LOB被解除链接。
注意:这意味着,如果您使用其他方法引用OID列以外的lob,那么vacuumlo可能会断开仍然需要的lob的链接!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | # vacuumlo -U postgres lob_test # p_ lob_test psql.bin (9.6.2) Type "help" for help. lob_test=# select generate_series as pageno, ( select count (*) from heap_page_items(get_raw_page( 'pg_largeobject' ,generate_series)) where t_infomask:: bit (16) & x '0800' :: bit (16) = x '0800' :: bit (16)) from generate_series(0,9); pageno | count --------+------- 0 | 0 1 | 0 2 | 0 3 | 0 4 | 23 5 | 107 6 | 107 7 | 107 8 | 107 9 | 61 (10 rows ) |
事实上,vacuumlo已经解除了对第一个LOB的链接,但是删除的元组在执行vacuum之前不会被释放:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | lob_test=# \lo_import /tmp/zeroes lo_import 16551 lob_test=# INSERT INTO t VALUES (3, 16551); INSERT 0 1 lob_test=# select generate_series as pageno, ( select count (*) from heap_page_items(get_raw_page( 'pg_largeobject' ,generate_series)) where t_infomask:: bit (16) & x '0800' :: bit (16) = x '0800' :: bit (16)) from generate_series(0,14); pageno | count --------+------- 0 | 0 1 | 0 2 | 0 3 | 0 4 | 23 5 | 107 6 | 107 7 | 107 8 | 107 9 | 107 10 | 107 11 | 107 12 | 107 13 | 107 14 | 38 (15 rows ) lob_test=# vacuum pg_largeobject; VACUUM lob_test=# \lo_import /tmp/zeroes lo_import 16552 lob_test=# INSERT INTO t VALUES (4, 16552); INSERT 0 1 lob_test=# select generate_series as pageno, ( select count (*) from heap_page_items(get_raw_page( 'pg_largeobject' ,generate_series)) where t_infomask:: bit (16) & x '0800' :: bit (16) = x '0800' :: bit (16)) from generate_series(0,14); pageno | count --------+------- 0 | 107 1 | 107 2 | 107 3 | 107 4 | 107 5 | 107 6 | 107 7 | 107 8 | 107 9 | 107 10 | 107 11 | 107 12 | 107 13 | 107 14 | 38 (15 rows ) |
因此,vacuumlo没有对pg_largeobject表进行任何清理。
原文:
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 解答了困扰我五年的技术问题
· 为什么说在企业级应用开发中,后端往往是效率杀手?
· 用 C# 插值字符串处理器写一个 sscanf
· Java 中堆内存和栈内存上的数据分布和特点
· 开发中对象命名的一点思考
· 为什么说在企业级应用开发中,后端往往是效率杀手?
· DeepSeek 解答了困扰我五年的技术问题。时代确实变了!
· 本地部署DeepSeek后,没有好看的交互界面怎么行!
· 趁着过年的时候手搓了一个低代码框架
· 推荐一个DeepSeek 大模型的免费 API 项目!兼容OpenAI接口!
2017-10-12 python的内置下载器