可以在 PostgreSQL 的表中存储 HTML 页面、图像、PDF 等文件还是很慢?看了一些文章说不推荐这个,不知道是不是真的。
我想到的列类型是BLOB
(据我所知它存储在文件中)或bytea
类型,但其他列类型也适用。
可以在 PostgreSQL 的表中存储 HTML 页面、图像、PDF 等文件还是很慢?看了一些文章说不推荐这个,不知道是不是真的。
我想到的列类型是BLOB
(据我所知它存储在文件中)或bytea
类型,但其他列类型也适用。
你基本上有两个选择。您可以将数据直接存储在行中,也可以使用大对象工具。由于 PostgreSQL 现在使用称为TOAST的东西将大字段移出表,因此直接在行中存储大数据应该不会造成性能损失。字段大小仍有 1 GB 的限制。如果这太有限或者如果您想要一个流式 API,您可以使用大对象工具,它为您提供更像数据库中的文件描述符的东西。您将 LO ID 存储在列中,并且可以从该 ID 读取和写入。
我个人建议您避免使用大型对象工具,除非您绝对需要它。使用 TOAST,只需按照您期望的方式使用数据库即可涵盖大多数用例。对于大型对象,您会给自己带来额外的维护负担,因为您必须跟踪您使用过的 LO ID,并确保在不再使用它们时(但以前不会)取消链接,否则它们会留在您的数据目录永远占用空间。还有很多设施在它们周围有异常行为,其中的细节让我无法理解,因为我从不使用它们。
对于大多数人来说,与在数据库中存储大数据相关的巨大性能损失是您的 ORM 软件将在每个查询中提取大数据,除非您明确指示它不要这样做。您应该注意告诉 Hibernate 或您使用的任何方法来将这些列视为大列,并且仅在特别请求时才获取它们。
BLOB (LO) 类型将数据存储在标准 PostgreSQL 堆页面中的 2KB 块中,默认大小为 8KB。它们不会作为独立的、有凝聚力的文件存储在文件系统中 - 例如,您将无法定位文件、进行逐字节比较并期望它与您的原始文件数据相同加载到数据库中,因为还有 Postgres 堆页面标题和描述块的结构。
如果您的应用程序需要频繁更新二进制数据,尤其是涉及大量小的随机访问写入时,您应该避免使用大对象 (LO) 接口,这是由于 PostgreSQL 实现并发控制 (MVCC) 的方式所致在您对数据库进行 VACUUM 之前,可能会导致使用的磁盘空间量激增。同样的结果可能也适用于内联存储在具有bytea类型甚至 TOAST'd 的列中的数据。
但是,如果您的数据遵循一次写入多次读取的模式(例如,上传PNG 图像并且之后永远不要修改它),那么从磁盘使用的角度来看应该没问题。
请参阅此 pgsql-general 邮件列表线程以进行进一步讨论。