首页 / 知识

在PostgreSQL中存储图像

2023-04-14 20:30:00

Storing Images in PostgreSQL

好吧,所以我正在开发一个应用程序,该应用程序将使用运行PostgreSQL的Linux后端来将图像提供给Windows盒,并且前端使用C#.NET编写,尽管前端几乎无关紧要。 我的问题是:

  • 在Postgres中处理图像的最佳方法是什么?

这些图像每个约为4-6百万像素,我们存储的图像多达3000个。可能还需要注意:这不是Web应用程序,最多将有大约两个前端同时访问数据库。


更新到2012年,当我们看到在所有应用程序中图像尺寸和图像数量都在不断增长时...

我们需要区分"原始图像"和"处理后的图像",例如缩略图。

正如Jcoby的回答所言,那么有两种选择,我建议:

  • 使用Blob(二进制大对象):用于原始图像存储,在您的桌子上。请参阅Ivan的答案(备份blob没问题!),PostgreSQL附加提供的模块,操作方法等。

  • 将单独的数据库与DBlink:用于原始图像存储,位于另一个(统一/专业化)数据库中。在这种情况下,我更喜欢bytea,但是blob几乎相同。分离数据库是"统一图像Web服务"的最佳方法。

  • 使用BYtea(BYTE阵列):用于缓存缩略图。缓存少量图像,以将其快速发送到Web浏览器(以避免呈现问题)并减少服务器处理。缓存基本元数据,例如宽度和高度。数据库缓存是最简单的方法,但是检查您的需求和服务器配置(例如Apache模块):将缩略图存储在文件系统中可能会更好,比较性能。请记住,这是一个(统一的)Web服务,然后可以存储在一个单独的数据库中(没有备份),该数据库可以服务许多表。另请参见PostgreSQL二进制数据类型手册,使用bytea列进行测试等。

注意1:今天不建议使用"双重解决方案"(数据库+文件系统)。使用"仅数据库"而不是双重使用有很多优点。 PostgreSQL具有可比的性能和用于导出/导入/输入/输出的良好工具。

注意2:请记住,PostgreSQL仅具有bytea,而没有默认的Oracle BLOB:" SQL标准定义了(...)BLOB。输入格式与bytea不同,但是提供的函数和运算符基本相同",手册。


EDIT 2014:今天我没有更改上面的原始文本(我的答案是12年4月22日,现在以14票),我为您的更改打开了答案(请参见" Wiki模式",您可以编辑!),以便进行校对和进行更新。
问题很稳定(@Ivans的'08答案为19票),请帮助改善本文。


关于jcoby的回答:

bytea是"常规"列,也意味着在获取值时会将其完全读取到内存中。相反,Blob可以流式传输到标准输出中。这有助于减少服务器内存占用。特别是当您存储4-6个MPix图像时。

备份Blob没问题。 pg_dump提供了" -b"选项,以将大对象包括到备份中。

因此,您可能会猜测,我更喜欢使用pg_lo_ *。

关于克里斯·埃里克森的回答:

我会说相反的话:)。当图像不是您唯一存储的数据时,除非绝对必要,否则不要将它们存储在文件系统中。始终确保您的数据一致性并将数据"合为一体"(数据库)是非常有益的。顺便说一句,PostgreSQL在保持一致性方面很棒。

但是,确实,现实通常对性能要求很高;-)会迫使您从文件系统提供二进制文件。但是即使那样,我仍倾向于使用DB作为二进制文件的"主"存储,所有其他关系始终保持链接,同时提供一些基于文件系统的缓存机制来优化性能。


在数据库中,有两个选项:

  • bytea。将数据存储在列中,作为备份的一部分导出。使用标准数据库功能进行保存和检索。根据您的需求推荐。
  • 斑点。将数据存储在外部,通常不作为备份的一部分导出。需要特殊的数据库功能才能保存和检索。

过去,我使用bytea列取得了巨大的成功,可存储10 + gb的图像并具有数千行。 PG的TOAST功能几乎抵消了Blob具有的任何优势。无论哪种情况,您都需要包含元数据列,以用于文件名,内容类型,尺寸等。


快速更新到2015年中期:

您可以使用Postgres Foreign Data界面将文件存储在更合适的数据库中。例如,将文件放入MongoDB的GridFS中。然后使用
https://github.com/EnterpriseDB/mongo_fdw
在Postgres中访问它。

这样做的好处是,您可以在Postrgres和MongoDB中访问/读取/写入/备份它,这取决于赋予您更多灵活性的东西。

还有用于文件系统的外部数据包装器:
https://wiki.postgresql.org/wiki/Foreign_data_wrappers#File_Wrappers

例如,您可以使用以下示例:
https://multicorn.readthedocs.org/en/latest/foreign-data-wrappers/fsfdw.html
(有关简要用法示例,请参见此处)

这为您提供了一致性(所有链接的文件都肯定存在)和所有其他ACID的优点,而实际文件系统中仍然存在这些文件,这意味着您可以使用所需的任何文件系统,并且Web服务器可以直接为它们提供服务(操作系统缓存也适用)。


10年后更新
在2008年,您要在其上运行数据库的硬盘驱动器将具有与要在其上存储文件的磁盘不同的特性,并且成本要高得多。如今,有更好的解决方案来存储10年前不存在的文件,我将撤销此建议,并建议读者研究此主题中的其他一些答案。

原版的

除非绝对必要,否则不要将其存储在数据库的图像中。我知道这不是Web应用程序,但是如果没有共享的文件位置,则可以指向将文件的位置保存在数据库中。

1
//linuxserver/images/imagexxx.jpg

那么也许您可以快速设置网络服务器并将网络网址存储在数据库中(以及本地路径)。尽管数据库可以处理LOB和3000张图像(4-6兆像素,假设500K图像),但1.5 Gig并不是很多空间文件系统比数据库更适合存储大文件。


尝试这个。我使用大对象二进制(LOB)格式在数据库中存储生成的PDF文档,其中一些文件大小超过10 MB。


如果图像较小,请考虑将它们作为base64存储在纯文本字段中。

原因是,尽管base64的开销为33%,但压缩几乎消失了。 (请参阅Base64编码的空间开销是多少?)您的数据库将更大,但您的Web服务器发送到客户端的数据包将不会更大。在html中,您可以在图像应用程序运行方法

最新内容

相关内容