如题,大概每个主条目下面关联有几张到一两百张不等的图片/文档之类的附件,每张图最大 500KB (入库时超大会自动压缩),文档也是不超过 500KB 。
目前测试数据(几十/百来个主条目)跑起来感觉挺香的,也没见什么性能问题。特别是设置好外键和 cascade delete 之后,主条目删除会自动把存 binary 的表中关联的附件一并干掉,比放文件系统好维护。文件系统还要自己处理数据关联和清理逻辑。
就是不知道以后数据量大了会有什么坑,预计之后主条目有数万个这样的量级。
1
KongLiu 23 小时 22 分钟前 ![]() 数据库占用 IO 太高了,高并发就废了,而且以后配合 CDN 做加速也不方便,还有数据库存储一般都比对象云存储贵把
|
![]() |
2
wangtian2020 23 小时 11 分钟前
我 sqlite 都不敢这么存
|
![]() |
3
liyafe1997 OP @KongLiu 没有什么太高的并发需求,正常用户应该没考虑到高并发这个量级,但是怕的是 Internet 上乱跑的爬虫/搜索引擎 Bot 之类的。
「以后配合 CDN 做加速也不方便」,这个为什么呢?我还想着以后用 CDN 来帮缓存一些图,不用每次都进我的后端/数据库 IO 。 |
4
zhengfan2016 22 小时 52 分钟前 ![]() |
![]() |
5
JYii 22 小时 50 分钟前
@liyafe1997 #3 你自己都说出隐患了,一个查询 api 就能把你 DB 打死。
|
![]() |
6
Vegetable 22 小时 45 分钟前
IO 很难受,这么弄也很难做到正常文件服务器的能力,本来如空气一般自然的功能你都得自己实现,比如 http 304 。
你如果一开始选了这个架构,后边会越来越难受,只有一开始能爽点,与其后边难受,不如一开始做好资源管理,把删除的逻辑弄好。 |
7
KongLiu 22 小时 43 分钟前
@liyafe1997 用 OSS 配置一下就好了,你这种方式全靠自己控制。搞不到 OSS 配置本身就提供的功能,你自己要写一大堆
|
![]() |
8
liyafe1997 OP @JYii 感觉在 HTTP Server 或者套一层 sqiud 做缓存能解决?甚至最外面还有一层 CDN 也能缓存?总之就是不用每次 HTTP GET 都去查 DB 。
|
![]() |
9
liyafe1997 OP @KongLiu 那还得装一套 OSS
|
![]() |
10
xtreme1 22 小时 39 分钟前
"条目"具体是什么东西?
|
![]() |
11
zephyru 22 小时 38 分钟前
CDN 一般不都是通过图片的文件路径地址去访问的?
存文件系统里直接上传对应文件保持路径,项目里替换下请求的地址就好了。 你这种模式也并不是不能用 CDN 但确实不方便。 小文件存数据库主要问题还是开销大吧,基本没见过正经系统把文件直接存数据库里的。 |
![]() |
12
liyafe1997 OP @xtreme1 你就理解成类似 V2EX 的帖子就好了,一条帖子下面可能挂有很多图片甚至文档等附件。
|
13
AutumnVerse 22 小时 36 分钟前 via iPhone
以前自己玩具项目这样搞过
就像楼上说的,数据库 io 扛不住,而且没法优化 |
![]() |
14
liyafe1997 OP @zephyru CDN 请求我的 Server 也是 HTTP GET 哇,我的后端访问数据库中的图片也是 HTTP GET ( RESTful API ),查 db 再把图 binary data 通过 http response 弹回给你
|
![]() |
15
liyafe1997 OP @AutumnVerse 现在想到的解决方案是在 HTTP Server 上做缓存,不知道加上这个之后,还有什么坑
|
16
AutumnVerse 22 小时 34 分钟前 via iPhone
正经做法是数据库存 oos 地址,后端返回 oos 地址,前端直接请求 oos ,这样减少服务端 io
|
17
AutumnVerse 22 小时 33 分钟前 via iPhone
@liyafe1997 缓存里面放图片?那你缓存的多大啊,你不怕缓存被撑爆吗
|
![]() |
18
liyafe1997 OP @AutumnVerse 不想(懒得)再引入一套 OSS 了🤣
|
19
AutumnVerse 22 小时 31 分钟前 via iPhone
直接放磁盘路径都比放数据库好,直接放磁盘有一些文件系统,操作系统相关的优化方案,而且可以挂载远程磁盘的方式做分布式
|
![]() |
20
liyafe1997 OP @AutumnVerse 直接放磁盘的话...我还是考虑 OSS 吧🤣
感谢解答 |
![]() |
21
zephyru 22 小时 29 分钟前
@liyafe1997
一般来说,大家说图片 CDN 可能是 OSS 那种模式的。 所有的流量全部走 CDN 不会再打到服务器上。 你这种情况,可能只适合使用套在域名上那种作为前置缓存的 CDN (缓存规则,失效诸如此类的先另说)。 你想使用传统使用 CDN 的方式,得先从 DB 里下载出来再上传,这就是麻烦的点。 这么看来主要的坑点,除了开销大,就是传统的方案需要你自己再另外实现。 |
![]() |
22
xtreme1 22 小时 28 分钟前
额, 就是富文本吗. 现在方案都很成熟了啊, 文本存 pg, 附件上 oss, 索引上 es.
|
23
KongLiu 22 小时 27 分钟前
@liyafe1997 能用和好用是两码事,你这个只能算是能用水平,远远谈不上好用。OSS 配合 CDN 能很容易的改变缓存策略,你这个每一点改动都要改代码。除非你这个项目是玩具项目做出来不用考虑维护的,不然早晚有坑等着呢,你现在的想象中的美好都基于没几个人用的情况。
|
24
chambered 22 小时 24 分钟前
我觉得 pg 的 bytea 就是用来存这些二进制数据的,所以几十 kb 应该没什么问题,太大肯定不行。还是看文档怎么介绍的吧
|
25
skallz 22 小时 10 分钟前 ![]() 之前只有富文本这么干过,当时是为了图省事把里面所有图片资源转成 base64 嵌在富文本里,但是后面也是相当难受,最后把富文本生成一个 json 文件传 oss 了
|
![]() |
26
ytmsdy 22 小时 9 分钟前 ![]() 数据库备份的时候,你就会知道这是一个噩梦,备份文件动不动就是上百 G 。
另外数据还原也是一个问题,很慢,很烦。 我们之前把身份证照片转成了 base64 ,存到了数据库里,然后自动备份服务器的空间动不动就满了。贼烦 |
![]() |
27
donaldturinglee 22 小时 9 分钟前
正经做法还是上 OSS
|
28
SoviaPhilo 22 小时 7 分钟前
除非硬件资源限制了, 最好是能分离, 毕竟如楼上说的方案很成熟了。
而方案成熟那是无数前人拿血和泪换来的。 另外, 数据量大了, 你现在的设计绝大多数都会是坑, 不止是图片。毕竟大数据量和小数据量在设计上肯定是不一样的 |
![]() |
29
kenilalexandra 22 小时 5 分钟前
OSS 的出现就是为了解决你不知道的“有什么坑吗”的
|
30
geminikingfall 21 小时 56 分钟前
这是个什么操作?这不上块存储吗?
|
![]() |
31
billbob 21 小时 44 分钟前
上 OSS
|
![]() |
32
liyafe1997 OP @ytmsdy base64 那会增大很多吧,正确不应该用 bytea?
|
33
jjx 21 小时 22 分钟前
500k 就是 5m 带宽了
两个人并发就带宽报警了 这种还是用 7 牛云之类的吧 |
![]() |
34
june4 20 小时 51 分钟前
楼上都没给出实锤证据啊,说明可行?
存成文件也是要 IO 的,且存数据库前面也可以配缓存,不管是文件缓存还是 CDN 缓存 可能就是备份比文件方式不方便一点,如果图片量是巨大的话。 |
![]() |
35
sagnitude 20 小时 43 分钟前 ![]() 没什么太大问题,不要被吓到了。
平时这种应用场景很少,所以大家没做过,可能第一反应就是反对。 我就举一个例子,GIS 地图服务器,比如卫星图的图片,一般都是存数据库里的,几十 TB 照样存,我见过的,sqlite ,postgresql ,mongodb ,都有。比如 postgresql 直接就有一个 PostGIS 扩展来做这个。 全国地图总数据量应该是 10 亿图片量级,存数据库也没问题。 才几万个根本无所谓的。 而且 sqlite 也可以的,关键是做好分库分表,我自己就做过 sqlite 地图服务,每个 sqlite 数据库最多存储大概 1-2GB 的数据,没什么问题。 为什么不用 OSS 或者文件系统?因为他扛不住哈哈哈,我一次性导 20 亿文件进去,OSS 要几个月,文件系统也要等一个月,RAID 也没什么用,存储最佳方式就是数据库,可以解决小文件碎片化的问题。 |
![]() |
36
irrigate2554 20 小时 33 分钟前
规模小的话应该没啥问题,memos 就支持存储附件到数据库,我也是这么用的。就怕规模越来越大,加上动不动 select * , 这样总有一天要炸。
|
![]() |
37
irrigate2554 20 小时 29 分钟前
有一个明显的劣势就是存视频的话流式播放功能就无法实现了。
|
![]() |
38
CEBBCAT 20 小时 23 分钟前
@sagnitude #35 请教下,是这个逻辑吗:OSS 是网络 IO(耗时),FS 是系统调用,SQLite 跑在用户空间,众所周知有时候可以比硬盘快
|
![]() |
39
sagnitude 20 小时 6 分钟前
@CEBBCAT
1. OSS 每一个操作都是网络,overhead 超级大,每个 stat 或者 mv cp 耗时增加哪怕 1 毫秒,乘以 20 亿的量级就是 23 天。几个月过去,项目都不要做了 2. 数据库可以用内存加速。 3. 文件系统对于巨量小文件的支持比较烂,碎片大,索引效率低,inode 就要占好几分之一的空间。 对数据库来说,读写是在单个文件内部完成的,不需要文件系统操作 open() close() |
![]() |
40
xiangyuecn 19 小时 52 分钟前
这么丁点数据量随便存,简单粗暴的存储架构,不要听楼上的,那些都是没卵用的提前优化
说不定项目黄了,数据库压力都不一定有上来 |
41
moen 19 小时 48 分钟前
pg 有个内置扩展叫 lo ,用来存大对象
|
![]() |
42
iyaozhen 19 小时 43 分钟前
可以这样吧,没啥问题。
而且你又不是经常 select * ,比如帖子附件,你可以只展示名称。下载再查出内容字段 当然 OSS 确实是标准做法 |
43
laminux29 19 小时 37 分钟前
全存数据库,最大的优势是开发与调试都极其方便,节约了程序员大量时间。就算后期性能不足,直接堆硬件也能解决。
大部分中小项目,这么跑一点问题都没有,而且数据库天生做负载均衡与 HA 都更方便。 当然,非常特殊的追求性能的项目,以及用户或数据量众多的大厂项目,可能没办法这么玩。 |
![]() |
44
KagurazakaNyaa 18 小时 56 分钟前
要存这种数据其实可以考虑用 mongo 这种文档数据库了,有 gridfs
|
45
xjzshttps 18 小时 54 分钟前
玩没问题,
但是数据库库扩展成本比文件系统大太多了。 |
47
delacey 17 小时 0 分钟前
到时候给你塞两张 1G 的图片,你的并发数不就炸了
|
![]() |
48
yplam 16 小时 46 分钟前 via Android
存文件系统的话通过 io copy 或者 zero copy (譬如 NGINX 的 sendfile )基本上可以忽略静态文件的内存开销,存数据库你是不是要整个文件内容都加载到内存然后再返回?或者你又要在前面加个 proxy cache ?
|
![]() |
49
liyafe1997 OP @sagnitude 我也觉得,左想右想都觉得没什么不妥,IO 问题就是在 HTTP Server 上加缓存的事。
|
![]() |
50
liyafe1997 OP @delacey 看题,不超过 500K
|
![]() |
51
liyafe1997 OP |
![]() |
52
RYAN0UP 7 小时 3 分钟前 via iPhone
|
![]() |
53
xiaohupro 6 小时 6 分钟前
还是建议最好使用单独的文件系统,而且现在很多开源的都很不错,也有对应的 API 提供,很方便,就像我自己用的就是 Zipline: https://zipline.diced.sh/docs/get-started
|
![]() |
54
wenning 5 小时 9 分钟前
没什么问题, 但是你参考一下云服务数据库磁盘的价格, 如果合适倒是可以的; 参考一下阿里云 rds 存储包,5t1 个月 6k 人民币
|
55
Huelse 4 小时 29 分钟前
关系数据库还是老老实实存数值字符串吧,其他类型的都有对应存储方案
|
56
DesmondCobb 4 小时 0 分钟前
@sagnitude #35 狠狠赞同了,之前搞医学数据库,数据集、影像、就诊记录等等文件又多又碎,用 SQLite 来存效率比文件显著提高,进行检索、关联也更容易
|
57
kirory 2 小时 0 分钟前
没什么问题,CDN 基本能全命中
最大问题就是数据库需要手动扩容 FS ,OSS 实际上也是 KV 数据库,这里对性能没有要求到要单独开服务器的程度,我不觉得为了*可能*的性能优势放弃单数据库的事务和一致性有好处 |
58
kirory 1 小时 50 分钟前
@irrigate2554 BLOB 是支持 stream 和 seek 的,肯定能实现流式播放,总不会直接直接把上 G 的文件直接全读内存里吧
|
59
thealert 1 小时 19 分钟前
@sagnitude #35 网络地图,2 进制存数据库根本不合理,你是查出数据库 2 进制返回给客户端,多个地图区块一次性查询数据库,并发用户量请求数据量一大接口直接爆掉了,每个区块需要做异步请求 cdn 才合适
|
![]() |
62
sagnitude 38 分钟前
@thealert 1. 基于 sqlite 分库分表,数据库根本不需要主从同步,平均 1GB 一个数据库文件,直接拷贝数据库文件分发到其他服务器就行,增加并发量可以简单的通过增加物理磁盘数量实现
2. 并发访问地图数据有内存缓存池子,sqlite 可以自己把部分数据加载到内存中读取,为何并发量会把接口爆掉?直接从内存返回数据还能被爆掉,那这台服务器上跑任何服务都会被爆掉 3. 地图请求天生都是连续的,因为用户看地图一定是一片连着一片看的,我收到第一个请求,直接把附近的数据加载到内存里,大概率马上就会被请求到,这一段读性能可以得到大幅优化 4. 不是单机地图,我都说了是 GIS 服务,提供标准 OGC 接口,WMS ,WMTS ,的 tile 服务 5. 为什么优先存数据库?地图数据不仅仅只有卫星图这种静态图像,还有高程图这种要随时读取内容并且用于计算的图像数据,还有矢量地图,架构肯定要统一 |
![]() |
63
sagnitude 30 分钟前
@thealert 而且最重要的原因上面也说了,磁盘存储和 OSS 存储和读写效率太低,我部署一次就要一个月,现在我的数据库导入、导出、更新大部分都可以在内存里做,最低最低也可以达到硬盘的读写极限,比读写小文件性能高太多了
|
![]() |
65
yh7gdiaYW 28 分钟前
说白了这个存数据库这个方案至少在初期可行,但除了给你开发省点力气,与存对象存储的方案相比没有任何好处。看你对现在这份干多久的预期了,过两年就跑就怎么省事怎么来
|
66
thealert 26 分钟前
@sagnitude #62
1 有些业务需要主从同步,跨机房延迟很高,分库分表解决不了高延迟问题 2 本质你是加载了缓存,和数据库就没关系了,但是图片是 ugc 的如何保证实时同步到缓存,我说的是用户请求大你每个用户都返回二进制图片网络接口带宽直接爆了 3 还是缓存问题其实就是 cdn |
![]() |
67
billbob 21 分钟前
没坑啊! PostgreSQL 就支持啊,只要支持,就能用.
业务增长,是否合理,那是未来你要考虑的,你前期设计个罗马出来,你也造不出来啊. 开发时间允许,可以放 OSS |
![]() |
68
sagnitude 21 分钟前
@thealert 如果抵达后端服务器的请求能把带宽撑爆,后端实现方式是数据库还是文件有区别吗; CDN 实际上就是把重复的直接拦截在前面了,我用数据库也可以用 CDN ,这个不影响
|
69
julyclyde 7 分钟前
文件系统也不过是(多级索引的)数据库
KV 存储也不过是数据库 用关系型数据库保存,其“不好”其实是取决于这个数据库的设计开发水平不好,而不是天生这个形式就不适用于这个用途 |
70
yannxia 1 分钟前
就没什么优点吧?
|