大型对象增强

来自 PostgreSQL 维基
跳转到导航跳转到搜索

此维基页面是关于为 二进制数据待办事项 开发的非官方待办事项的备忘录。

TOAST 值上的大型对象接口

TOAST 关系定义如下,它是一个存在于pg_largeobject.

pg_toast_%u (
    chunk_id        oid,
    chunk_seq       int4,
    chunk_data      bytea,
    unique(chunk_id, chunk_seq)
)
pg_largeobject(
    loid            oid,
    pageno          int4,
    data            bytea,
    unique(loid, pageno)
)

中的相同结构。将大型对象的内容部署到其 toast 关系上,以及将大型对象接口增强以访问 toast 数据结构的部分内容,这是很自然的。在这种情况下,pg_largeobject将被用来管理大型对象的元数据。

它也能够解决非常大的TEXTBYTEA数据中的一个问题。在规范中,它允许存储 1G 字节长度的 varlena 数据,但它需要在提取时将整个块数据帧扩展到本地内存中。显然,这对于存储非常大的数据是不合适的。

问题

Toast 格式

当给定的数据被 toasted 时,它可以被压缩以减少存储消耗,对于 attstorage 为 'm' 或 'x' 的列。然而,这使得难以估计哪个块存储了所需的数据区域,因此它不适合部分访问。当前TEXTBYTEA类型定义为pg_type.typstorage为 'x',因此需要一种新的 varlena 类型来存储未压缩的数据以允许部分访问。

当 varlena 数据足够小时,它可以存储在元组内,无需任何外部 toast 关系。然而,这使得无法部分更新它们,因为它需要整个更新。

因此,允许大型对象接口的新 varlena 数据类型必须具有以下特性:

  • 它总是使用外部 toast 关系,独立于给定 varlena 的大小。
  • 它永远不会压缩给定的 varlena,以便正确地估计哪个块存储了哪个偏移量。

在我的计划中,一种新的 varlena 类型BLOB将被添加,并具有上述要求。

块的空洞

当前的 TOASTing 机制没有考虑块的空洞。大型对象功能可以包含不连续的页面帧。如果我们尝试读取有空洞的页面,它会返回零填充的页面。重新设计的 TOASTing 机制需要处理有空洞的页面。

一个有争议的事情是,应该从toast_raw_datum_size()toast_datum_size().

返回什么值

模式支持

语句

postgres=# CREATE SCHEMA lotest;
CREATE SCHEMA
postgres=# ALTER LARGE OBJECT 1234 SET SCHEMA lotest;
ALTER LARGE OBJECT
postgres=# DROP SCHEMA lotest;
ERROR:  cannot drop schema lotest because other objects depend on it
DETAIL:  largeobject 1234 depends on schema lotest
HINT:  Use DROP ... CASCADE to drop the dependent objects too.
postgres=# DROP SCHEMA lotest CASCADE;
NOTICE:  drop cascades to largeobject 1234
DROP SCHEMA

ALTER LARGE OBJECT

CREATE LARGE OBJECT在我看来,CREATE [TEMP] LARGE OBJECT

使用完全限定的命名空间是一个有用的功能。

命名大型对象

postgres=# SELECT lo_open('my_lobject', x'40000'::int);
postgres=# SELECT lo_open('pg_temp.your_lobject', x'40000'::int);

目前,大型对象接口只支持数字标识符,但是,使用人类可读标识符并不不可能,如下所示后面的例子通过pg_temp

模式限定了大型对象的名称。

创建大型对象的权限在数据库 DAC 模型中,ACL_CREATE

在存储新数据库对象的模式上进行检查,但是,大型对象不受任何特定模式的支配。如果我们需要检查创建大型对象的权限,则需要用某个模式对象来覆盖它。

已完成的项目

为大型对象添加安全检查这提供了对大型对象的拥有权和读/写权限管理的支持。该readwrite权限是显而易见的。这些应该在, loread()lowrite()lo_truncate()上进行检查。此外,只有大型对象的拥有者(以及超级用户)可以使用.

lo_unlink()

删除它们。数据结构一个新的系统目录,用来管理大型对象的元数据(所有权和安全属性),与页面帧分开。该pg_largeobject_metadata.oid.

pg_largeobject.loid

GRANT