MySQL - Base64与BLOB的区别

29
为了简化问题,假设我正在开发一个像Instagram的移动应用程序。用户可以从服务器下载图像,并上传自己的图像。目前,服务器将所有图像(实际上仅为小缩略图)存储在MySQL数据库中作为BLOBs。似乎最常见的传输图像的方式是使用Base64编码,这让我有两个选择:
  1. 服务器将所有图像都存储为BLOBs。要上传图像,客户端将其编码为Base64字符串,然后将其发送到服务器。服务器将图像解码回二进制格式,并将其存储在数据库中作为BLOB。当客户端请求图像时,服务器将重新将图像编码为Base64字符串并将其发送给客户端,客户端再将其解码回二进制以进行显示。
  2. 服务器将所有图像都存储为Base64字符串。要上传图像,客户端将其编码为Base64字符串并将其发送到服务器。服务器不进行编码或解码,而是直接将字符串存储在数据库中。当客户端请求图像时,将返回Base64字符串给客户端,客户端再将其解码以进行显示。
显然,选项1需要服务器进行更多处理,因为每个请求都必须对图像进行编码/解码。这使我倾向于选项2,但一些研究表明,在MySQL中存储Base64字符串比直接将图像存储为BLOB要不高效得多,并且通常不建议这样做。
我肯定不是第一个遇到这种情况的人,所以有人有关于使其工作的最佳方法的建议吗?

2
选项#3是首先没有数据库中的图像。他们为此拥有一个系统:文件系统。 - tadman
2
我最开始是储存文件路径的,但是最新版本的MySQL的一些研究建议说将小于1或2mb的文件作为BLOBs来存储更加有效率。我的图片只有几kb,所以这种方式更易于维护。 - Hundley
备份一个包含大量二进制大对象(BLOB)的数据库是一场绝对的噩梦。复制这些数据非常昂贵,备份它们也很昂贵,恢复它们极其痛苦,当它们变得太大时,拆分它们更是难上加难。除非你处理的数据量微不足道,否则这个问题最终会让你崩溃。使用像“rsync”这样基本的工具可以轻松地复制磁盘上的文件,但对于MySQL来说并非如此。 - tadman
3个回答

12

JSON假定使用utf8编码,因此除非以某种方式编码,否则与图像不兼容。

Base64几乎比二进制(BLOB)多8/6倍。可以说它很容易承受。 3000个字节变成大约4000个字节

每个人都应该能够接受任意的8位编码,但并非所有人都这样做。 Base-64可能是最简单的,总体上最好的妥协方案,用于不必处理8位数据。

由于这些是“小”的,我会将它们存储在表中而不是文件中。但是,我会将它们存储在一个单独的表中,并通过适当的id进行JOIN,在需要它们时使用。这样可以使不需要图像的查询运行速度更快,因为它们不会步进BLOB。

从技术上讲,TEXT CHARACTER SET ascii COLLATE ascii_bin可以使用,但BLOB可以更清楚地表明列中没有可用的文本。


请澄清一下,您是建议我将图像存储为Base64格式的BLOB,还是存储二进制数据并在每次获取时进行编码?至于您关于JOIN的建议 - 这正是我正在做的,同时还使用Sphinx索引。 - Hundley
Base64在其生命周期内一直存在。因此,您不需要在任何地方进行转义。所以,是的,在BLOB中使用Base64时不需要编码,除了初始插入之外。这是我的观点。 - Rick James
有趣的想法,也许我会尝试一下。这肯定会节省很多 CPU,因为获取操作比插入操作频繁得多。 - Hundley

0
你为什么要在传输过程中对图像进行Base64编码呢?我认为你的前提是错误的。

你能澄清一下吗?目前我正在发送所有图像作为Base64编码的JSON对象,还有一些元数据(这样客户端就知道在收到图像后该怎么做)。有没有办法将图像作为二进制对象(无编码)与元数据一起发送?客户端如何POST一个新图像?我的服务器使用Node.js和Express进行HTTP,以及ws用于一些WebSocket功能。 - Hundley
如果我们不通过网络传输数据,我同意这是不好的。如果客户端需要显示存储在数据库中的图像,您有什么建议?我猜想使用网页链接是唯一的选择了?但是我们的数据库已经在一个列中包含了成千上万个base64编码的图像。欢迎任何帮助。 - j2emanue
这应该是一条注释,肯定不是一个答案。 - Mario Gil

0

我不明白为什么数据库服务器不应该始终以其本地格式保存二进制数据。因此,使用BLOB。(但即使您将数据存储在Base64字符串中,也无需担心编码/解码性能,因为IO的影响将更显著。)

但我不明白为什么客户端应该以base64发送数据。为什么不使用简单的HTTP调用“流式传输”呢?


转换为“二进制流”需要在协议等方面进行一些调整。HTTP仅接受有限的256种不同字节组合,并具有应对其他组合的解决方法。Html-entities就是其中之一,但它非常笨重。反斜杠是另一个,但并不能涵盖所有情况。将8位代码转换为3个字节的Url编码等。等等。 - Rick James

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接