当前位置:首页 > 问答 > 正文

图像存储到底用啥数据库才靠谱,选对了效率才高,不然就麻烦多多

图像存储到底用啥数据库才靠谱,选对了效率才高,不然就麻烦多多,这个问题可真是问到点子上了,现在谁的应用里还没点图片视频啊,选不好后面全是坑,爬都爬不出来,你别看那些专业文章讲得天花乱坠,咱今天就捞干的说,用大白话把这事儿捋清楚。

咱得明白图片数据有个最大的特点:它自己个儿挺大的,但描述它的信息(比如图片名、上传时间、谁上传的、属于哪个相册)又是很小的一段文字,这就带来了第一个纠结:是把图片本身和这些描述信息一起存到传统的数据库里(比如MySQL、PostgreSQL),还是分开存?

所有东西都塞进传统关系型数据库

早些年,很多人这么干,就是把图片文件转换成二进制数据,直接塞进数据库表的一个大字段里,这么做听起来挺省事儿,所有数据都在一起,备份啊、管理啊好像简单点。(来源:一些早期的Web开发实践)

但为啥现在大家基本都不用这招了呢?因为太伤性能了,你想啊,每次用户看个图,数据库都得吭哧吭哧把巨大的二进制数据捞出来,这非常消耗数据库的CPU和内存,数据库本来是擅长处理小规模、结构化的数据的,你让它天天干这种搬大砖头的体力活,它肯定慢给你看,尤其是图片一多,数据库体积暴增,备份恢复一次能让你等到花儿都谢了,这条路子现在基本被证明是条弯路,除非你存的都是特别小的图标类图片,否则千万别这么干。

图片文件存服务器硬盘,数据库只存路径

这是最经典、最普遍的做法,直到今天很多中小型项目还在用,方法很简单:图片文件就上传到服务器的某个目录下,/uploads/images/2023/10/xxx.jpg,在数据库里,比如你的“用户表”或者“文章表”里,只存这个图片的访问路径就行了。

这法子好处很明显:轻量,数据库只存个字符串路径,压力小,跑得飞快,服务器直接通过文件系统读写图片,简单粗暴。(来源:广泛的Web应用开发经验)

那麻烦在哪儿呢?首先就是扩容和备份变复杂了,你的应用要是只有一台服务器,那没问题,可万一火了,需要多台服务器做集群呢?图片只存在其中一台服务器的硬盘上,其他服务器就找不到了,你得想办法让所有服务器都能访问到同一个文件存储位置,这就得引入共享存储或者文件同步机制,搞起来就有点头大了。备份的时候,你不仅得备份数据库,还得记得把整个图片目录也备份了,容易遗漏,直接靠文件系统的话,想做一些高级功能,比如图片处理(生成缩略图、加水印)、权限控制,都得自己写代码实现,比较麻烦。

用专门的对象存储服务(比如阿里云OSS、腾讯云COS、AWS S3)

这可以说是目前解决图片存储问题的“黄金标准”,尤其是对需要扩展、追求稳定和方便的项目,对象存储你可以理解成一个超级无限大、还特别可靠的网络硬盘。

你用对象存储,流程是这样的:用户上传图片,你的服务器后台接收到之后,直接转手就上传到对象存储服务商那里去,上传成功后,对象存储会返回一个唯一的网址(URL),你这个URL存到自己的数据库里就行了,以后用户要访问图片,直接通过这个URL就能从对象存储那边下载,甚至都不用经过你的服务器。

这招好处太多了:一是无限扩容,你根本不用操心硬盘够不够。二是特别可靠,这些大厂的服务商会把你的图片在不同地方存好几个备份,几乎不可能丢。三是功能强大,很多对象存储服务自带图片处理功能,比如你可以在URL后面加参数,直接获取不同尺寸的缩略图,都不用自己提前生成。四是节省带宽,图片流量压力都给了对象存储商,你的服务器带宽压力就小多了。(来源:主流云服务商对象存储产品文档)

这也不是没缺点,最大的缺点就是要花钱,虽然前期可能很便宜,但流量大了、存储量大了,费用也会上去,你的数据是放在第三方那里的,如果对数据隐私有极端高的要求,可能需要斟酌。

用NoSQL数据库存图片

还有些NoSQL数据库,比如MongoDB,它自带一种叫“GridFS”的机制,就是专门设计来存储大文件(包括图片)的,它的原理是把大文件切分成很多小块来存,用的时候再组合起来。

这种做法介于路子一和路子二之间,它没有直接把大二进制数据塞进常规文档里,而是用了更聪明的方式管理大文件。(来源:MongoDB官方文档)

那什么时候考虑用它呢?主要是当你整个项目的数据都在用MongoDB,而且图片量不是天大的那种,你可能为了技术栈统一,就顺手用GridFS存了,这样好歹所有数据(包括图片)都在一个数据库系统里,管理起来一致性好,但它的性能和处理大流量的能力,通常还是不如专门的对象存储服务。

到底咋选?

看到这儿,你心里应该有点数了。

  • 如果你就是个个人博客、小公司官网,图片不多,访问量也不大,那用“文件存硬盘,数据库存路径”的老法子,最经济实惠,完全够用。
  • 如果你做的是移动App、电商平台、社交网站这类图片量大、访问频繁、而且未来可能快速增长的项目,别犹豫,直接上对象存储,花点小钱,省心省力,为未来铺好路,这才是真正“效率高”的选择。
  • 除非有特殊原因,比如公司规定所有数据必须在自己机房,或者你的技术架构已经重度依赖MongoDB且图片不是核心负载,否则一般不去考虑把图片塞进数据库(无论是关系型还是NoSQL)的方案。

选对了,后面顺风顺水;选错了,光是迁移数据就能把你折腾掉半层皮,所以前期多花点时间琢磨清楚,绝对值得。

图像存储到底用啥数据库才靠谱,选对了效率才高,不然就麻烦多多