压缩表

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


此页面包含 **历史信息或已弃用文章**。

v0.1 2007 年 12 月 11 日

大型数据存档通常需要减少数据占用空间,以降低长期存储成本。

对于仅插入数据,我们可以通过删除未使用的元组头信息来减小表的大小。尽管这是可能的,但重复的头部压缩效果很好,因此直接使用压缩表来解决这个问题似乎更容易。

使用像 zlib 这样的流式库,可以轻松地将数据文件读写到一个仍然可用的形式,但大小会大大减小。只有作为 SeqScan 访问压缩表才有意义。这将通过引入特定于表空间的访问成本来处理,下面将讨论。压缩表上的索引仍然允许,但几乎不会使用。

访问可能通过特定于表空间的存储管理器进行。因此,在 src/backend/storage/smgr 中与 md.c 一起实现 mdcompress.c。如果选择这种实现路线,那么压缩选项就可以在表空间级别进行,因此命令将是

CREATE TABLESPACE tablespacename LOCATION 'directory' [COMPRESS];

(ALTER TABLESPACE 支持会更加复杂,所以现在先放一边)

因此,当我们将只读表复制到另一个表空间时,压缩将在 ALTER TABLE 级别进行,无需额外的语法。即在 tblcmds.c 中不会有任何新的内容。很酷。

mdcompress.c 看起来很简单,不过我们需要考虑如何实现 smgr_nblocks(),因为使用 lseek 获取它不会起作用,因为文件大小小于实际解压缩的表。也许可以用一个包含类似索引元页面的信息文件,我们可以在其中读取块数。有什么想法吗?

在第一阶段,我只允许压缩的只读表。随着时间的推移,我们可能会允许插入、更新和删除,尽管后两种操作永远不会非常有效。因此,我的初始方法*不允许*直接写入压缩表。这样做不可取/不容易的原因有以下几个:如果我们直接将数据写入表,那么任何中止的加载都将写入表,因此 VACUUM 表需要重新压缩表,这听起来很糟糕。此外,提示状态位需要在数据写入*之后*设置。(也许结合可见性图,我们可以忽略这方面的内容。)另一个问题是块需要按顺序写入共享缓冲区,不幸的是,我们不能保证这一点。我们可以在 smgr 层强制执行这一点,方法是跟踪最后一个写入的块 ID,然后将所有缓存块写入当前请求的块,但这似乎有问题。我认为,如果我们想要更多,我们会在下一个版本或至少是下一个开发阶段进行。因此,现在我们将会阻止在 COMPRESSED 表空间上直接使用 CREATE TABLE。

我欢迎大家提出论点,认为我们根本不需要这个,因为存在可以完成我们所需一切的文件系统实用程序。关于此功能,您的经验将非常有用。