在PostgreSQL中存储图像

jyztefdp  于 2023-11-18  发布在  PostgreSQL
关注(0)|答案(8)|浏览(321)

好吧,我正在开发一个应用程序,它将使用运行PostgreSQL的Linux后端向前端用C#.NET编写的Windows机器提供图像,尽管前端几乎不重要。我的问题是:

*在Postgres中存储图片的最佳方法是什么?

每个图像大约有4-6百万像素,我们存储了3000多个图像。值得注意的是:这不是一个web应用程序,最多有两个前端同时访问数据库。

t3irkdon

t3irkdon1#

更新到2012年,当我们看到图像大小和图像数量在所有应用程序中都在不断增长...
我们需要在“原始图像”和“处理后的图像”之间进行一些区分,如缩略图。
正如Jcoby的回答所说,有两种选择,那么,我建议:

  • use blob(Binary Large OBject):用于原始镜像存储,在你的table上。参见Ivan的回答(备份blob没有问题!),PostgreSQL additional supplied modulesHow-tos等。
  • 使用一个单独的数据库DBlink:用于原始图像存储,在另一个(统一/专用)数据库。在这种情况下,我更喜欢 bytea,但 blob 几乎相同。分离数据库是“统一图像Web服务”的最佳方式。
  • 使用 bytea(字节数组):用于缓存缩略图。缓存小图像以快速发送到Web浏览器(以避免渲染问题)并减少服务器处理。缓存重要的元数据,如宽度和高度。数据库缓存是最简单的方法,但请检查您的需求和服务器配置。(例如Apache模块):store thumbnails at file system可能更好,比较性能。请记住,它是一个(统一的)Web服务,然后可以存储在一个单独的数据库(没有备份),服务于许多表。参见PostgreSQL binary data types manualtests with bytea column等。

注1:今天"dual solutions" (database+filesystem)的使用被弃用了(!)。使用“only database”代替dual有很多优点。PostgreSQL有相当的性能和很好的导出/导入/输入/输出工具。
注2:请记住,PostgreSQL只有 bytea,没有默认的Oracle的 BLOB:“SQL标准定义了(...)BLOB。输入格式与bytea不同,但提供的函数和运算符大多相同”,Manual
编辑2014:我今天没有改变上面的原始文本(我的答案是Apr 22 '12,现在有14票),* 我正在为您的更改打开答案 *(请参阅“Wiki模式”,您可以编辑!),为proofreading为更新
这个问题是稳定的(@Ivans '08的答案有19票),请帮助改进这篇文章。

kq0g1dla

kq0g1dla2#

jcoby的回答:
bytea是一个“普通”列也意味着当你获取它时,值会被完全读入内存。相反,你可以将Blob流到stdout中。这有助于减少服务器内存占用。特别是当你存储4-6 MPix图像时。
备份blob没有问题。pg_dump提供了“-b”选项来将大型对象包含到备份中。
所以,我更喜欢使用pg_lo_*,你可能猜到了。
Kris Erickson的回答:
我会说相反的:).当图像不是你存储的唯一数据时,除非你绝对必须,否则不要将它们存储在文件系统上。总是确保数据的一致性,并使数据“在一块”(数据库)是一个好处。顺便说一句,PostgreSQL在保持一致性方面很棒。
然而,现实往往对性能要求太高;-),它迫使你从文件系统中提供二进制文件。但即使这样,我还是倾向于使用DB作为二进制文件的“主”存储,所有其他关系都一致地链接,同时提供一些基于文件系统的缓存机制来优化性能。

a5g8bdjr

a5g8bdjr3#

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

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

我曾经使用bytea列成功地存储了10 GB以上的图片和成千上万的行。PG的吐司功能几乎否定了blob的任何优势。无论哪种情况,你都需要包括文件名,内容类型,维度等的元数据列。

e5nszbig

e5nszbig4#

2015年中期快速更新:

您可以使用Postgres Foreign Data接口,将文件存储在更合适的数据库中。例如,将文件放在GridFS中,GridFS是MongoDB的一部分。然后使用https://github.com/EnterpriseDB/mongo_fdw在Postgres中访问它。
这样做的好处是,你可以在Postrgres和MongoDB中访问/读/写/备份它,这取决于什么能给你更大的灵活性。

**文件系统也有外来数据 Package 器:**https:wiki.postgresql.org/wiki/Foreign_data_wrappers#File_Wrappers

作为一个例子,你可以使用这个:https://multicorn.readthedocs.org/en/latest/foreign-data-wrappers/fsfdw.html(见这里的简要用法示例)
这为您提供了一致性(所有链接文件肯定都在那里)和所有其他ACID的优势,而实际文件系统上仍然存在,这意味着您可以使用任何您想要的文件系统,并且Web服务器可以直接为它们提供服务(操作系统缓存也适用)。

gxwragnw

gxwragnw5#

10年后更新在2008年,你运行数据库的硬盘驱动器将具有与你存储文件的磁盘不同的特性和更高的成本。现在有更好的解决方案来存储10年前不存在的文件,我会撤销这个建议,并建议读者看看这个线程中的其他一些答案。
原件

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

//linuxserver/images/imagexxx.jpg

字符串
那么也许你可以快速设置一个web服务器并将web url存储在数据库中(以及本地路径)。虽然数据库可以处理LOB和3000个图像(4-6百万像素,假设一个图像500 K)1.5 Gigs并不是很多空间文件系统比数据库更适合存储大文件。

ifmq2ha2

ifmq2ha26#

如果你的图像很小,考虑将它们存储为base64在纯文本字段中。
原因是base64有33%的开销,压缩大部分都消失了。(参见What is the space overhead of Base64 encoding?)你的数据库会更大,但你的web服务器发送到客户端的数据包不会更大。在html中,你可以在标签中内联base64,这可能会简化您的应用程序,因为您不必在单独的浏览器获取中提供二进制图像。将图像作为文本处理也简化了事情当你必须发送/接收JSON时,它不能很好地处理二进制。
是的,我知道你可以将二进制文件存储在数据库中,并在进出数据库的过程中将其转换为文本,但有时ORM会让这变得很麻烦。将其视为直接文本可能会更简单,就像所有其他字段一样。
这绝对是处理缩略图的正确方法。
(OP的图像并不小,所以这并不是真正回答他的问题。)

e4yzc0pl

e4yzc0pl7#

小行星2022
现在最常见的模式是只在数据库中存储对映像的引用,并将映像本身存储在文件系统(即S3存储桶)中。
好处是数据库备份更小,不再有单点故障,负载现在可以从数据库中分散,云存储桶通常比数据库存储便宜。
缺点是你必须在两个位置管理图像-删除一个图像,你的应用程序需要跟踪并从另一个位置删除它。

0ve6wy6x

0ve6wy6x8#

2023答案:使用CDN。
将图像粘贴在数据库中是很诱人的,但设置CDN需要5分钟,它们很便宜,它们会自动优化交付,等等。
您的API响应将明显更小,您的图像加载速度明显更快,CDN可以自动生成缩略图,裁剪,转换等。
在某些特殊情况下,将图像存储在数据库中是有意义的,但将其视为比使用CDN更复杂的选项,并且有很好的理由。
即使是玩具应用程序,使用CDN也会为您节省很多麻烦。

相关问题