Spi*_*ike 9 postgresql blob postgresql-9.1
我在 Postgres 9.1 数据库中有两个表 ( table1, table2)。两者都有 oid 类型。每张表100万条记录。而pg_largeobject表的大小约为40GB。我从每个表中删除了 90 万条记录,并执行了以下命令。
vacuum full analyze table1;
vacuum full analyze table2;
Run Code Online (Sandbox Code Playgroud)
pg_largeobject表大小仍然没有变化(启用自动真空)
我也需要执行上面的命令来pg_largeobject表吗?会影响什么吗?
Erw*_*ter 15
你可以运行它,没问题:
VACUUM FULL ANALYZE pg_largeobject;
Run Code Online (Sandbox Code Playgroud)
甚至可能删除一些死行。细节:
但它可能不会解决您的实际问题。
当使用Postgres的大对象设施时,大对象(“blob”:二进制大对象)本身被分解成存储在系统表中的二进制数据块pg_largeobject。的PK由两列组成(loid, pageno),loid是oid被用于指在用户表(一个或多个)的斑点。OID可以多次引用同一个 blob 。
删除用户表中的行不会删除 blob。一方面,同一个 blob 可能被多次引用。您有责任自己跟踪并实际删除“未链接”的 Blob。一种方法是使用lo_unlink():
SELECT lo_unlink(173454); -- deletes large object with OID 173454
Run Code Online (Sandbox Code Playgroud)
由于您已经删除了带有oid引用的行,因此您需要更有创意来识别未链接的 blob。假设您没有从任何其他地方引用 blob,您可以使用此查询来修复:
SELECT lo_unlink(l.loid)
FROM pg_largeobject l
GROUP BY loid
HAVING (NOT EXISTS (SELECT 1 FROM table1 t WHERE t.oid = l.loid))
AND (NOT EXISTS (SELECT 1 FROM table2 t WHERE t.oid = l.loid));
Run Code Online (Sandbox Code Playgroud)
您需要成为超级用户才能pg_largeobject直接访问。在假定列名table1与table2是oid。基于pg_largeobject_metadataPostgres 9.3 或更高版本的更简单的查询(如@Daniel 评论):
SELECT lo_unlink(l.oid)
FROM pg_largeobject_metadata l
WHERE (NOT EXISTS (SELECT 1 FROM table1 WHERE t.oid = l.oid))
AND (NOT EXISTS (SELECT 1 FROM table2 WHERE t.oid = l.oid));
Run Code Online (Sandbox Code Playgroud)
pg_largeobject_metadata是公开可读的。但是我在 pg 9.3 (包括 pg 9.1)之前的版本中没有在系统表中看到 blob 的 OID - 至少在手册中没有,我现在没有要测试的旧版本。所以你可能必须使用我的第一个查询。
前后对比:
SELECT count(*) FROM pg_largeobject;
SELECT pg_size_pretty(pg_table_size('pg_largeobject'));
Run Code Online (Sandbox Code Playgroud)
您VACUUM FULL现在可以运行,然后再次测试:
VACUUM FULL ANALYZE pg_largeobject;
Run Code Online (Sandbox Code Playgroud)
您会对Postgres 9.1 可用的附加模块lo感兴趣。该手册对您的问题有准确的描述:
...一个表条目可以通过 OID 引用一个大对象,但是可以有多个表条目引用同一个大对象 OID,因此系统不会仅仅因为您更改或删除一个这样的条目就删除大对象。
大胆强调我的。该模块也提供了一个解决方案:
该
lo模块允许通过将触发器附加到包含 LO 引用列的表来解决此问题。触发器基本上只是lo_unlink在您删除或修改引用大对象的值时执行。
对于每个斑被引用的使用情况究竟在你的整个数据库一次。
显然也(如@Daniel 提到的)vacuumlo:
vacuumlo 是一个简单的实用程序,它将从 PostgreSQL 数据库中删除任何“孤立的”大对象。