在PostgreSQL中存储文件是否存在性能问题?

时间:2012-03-07 16:59:48

标签: file postgresql blob bytea

可以在PostgreSQL中的表格中存储像HTML页面,图像,PDF等文件,还是很慢?我读了一些文章说这不推荐,但我不知道是否属实。

什么是最好使用,存储为BLOB(它存储在文件中,对吗?)还是存储在bytea类型的列中?

2 个答案:

答案 0 :(得分:46)

你基本上有两种选择。您可以将数据存储在行中,也可以使用大型对象工具。由于PostgreSQL现在使用名为TOAST的东西将大字段移出表格,因此直接在行中存储大数据不会产生性能损失。字段大小仍有1 GB的限制。如果这个太有限或者您想要一个流API,您可以使用大型对象工具,它可以为您提供更像数据库中的文件描述符。您可以将LO ID存储在列中,并可以从该ID读取和写入。

我个人建议你避免使用大型物体设施,除非你绝对需要它。使用TOAST,只需使用您期望的数据库即可覆盖大多数用例。使用大型物体时,您会给自己额外的维护负担,因为您必须跟踪您使用的LO ID,并确保在不再使用它们时(但之前不再使用它们)取消链接它们或者它们将位于您的数据目录永远占用空间。还有很多设施都有特殊的行为,其中的细节让我感到厌烦,因为我从不使用它们。

对于大多数人来说,在数据库中存储大数据所带来的巨大性能损失是,您的ORM软件会在每个查询中提取大数据,除非您明确指示不这样做。您应该注意告诉Hibernate或者您正在使用的任何内容将这些列视为大型,并且仅在特别请求时才获取它们。

答案 1 :(得分:8)

BLOB(LO)类型在标准PostgreSQL堆页面中以2KB块存储数据,默认大小为8KB。它们不会作为独立,有凝聚力的文件存储在文件系统中 - 例如,您将无法找到该文件,进行逐字节比较并期望它与您原始文件数据相同加载到数据库中,因为还有Postgres堆页面标题和结构,用于描述块。

如果你的应用程序需要经常更新二进制数据,你应该避免使用大对象(LO)接口,特别是如果它涉及大量小的随机访问写入,这是由于PostgreSQL实现并发控制的方式(MVCC)可能导致在您使用VACUUM数据库之前所使用的磁盘空间量激增。相同的结果可能也适用于以 bytea 类型甚至TOAST'd列在内联存储的数据。

但是,如果您的数据遵循“一次写入多次读取”模式(例如,上传PNG图像并且之后从不对其进行修改),则从磁盘使用的角度来看应该没问题。

有关进一步的讨论,请参阅this pgsql-general mailing list thread