本节摘要:通用数据库用一套 B+ 树和 SQL 去服务所有场景,到了向量、时序、图、全文搜索这些领域,就成了拿锤子拧螺丝。专门化存储系统承认数据形态不同,各自定制引擎:时序库为时间窗口聚合而生,图库把关系遍历做成原生操作,向量库把相似度计算沉到索引里,搜索引擎为倒排索引调优。本节讲清四类系统各解决什么问题、核心结构是什么、什么时候该用、什么时候是过度设计。读完你应当能对专库专用做出有依据的判断。
阅读完本节,你应当能够:
通用数据库是个百货商店,什么都卖,但什么都不精。它用一张关系表去装所有数据,用 B+ 树去索引所有字段,用 SQL 去表达所有查询。这在很长一段时间里够用,因为那时的数据长得都差不多——无非是订单、用户、库存这些规规矩矩的二维表。
可后来数据形态分化了。物联网每秒喷出百万级传感器读数,这是按时间排队的流;社交网络里几亿个节点和几十亿条边,这是图;大模型把文本、图片压成几百维的向量,这是高维空间里的点;还有海量的日志和文档,这是要全文检索的非结构化文本。把这些东西硬塞进关系表,问题就来了。
举三个具体的例子。第一个是"好友的好友"这类多跳查询。在关系库里,你得把好友表和自己 JOIN 两次、三次,每一次 JOIN 都是一次全表扫描加哈希匹配,深度越大,代价指数级上升。一个三层关系查询,可能在关系库里要跑几十秒,而在图库里是毫秒级——因为图库把"从一个节点找它的所有出边"做成了原生操作。
第二个是向量相似搜索。你要在一千万张图片里找和某张图最像的十张,这在关系库里只能把每个向量的距离都算一遍,线性扫描,慢得没法用。而向量库用近似最近邻索引,把复杂度从线性降到对数级,代价是允许一点点召回率的损失。
第三个是时序聚合。你要查"过去一小时每分钟的平均 CPU 使用率",这在关系库里要先扫出这一小时的上百万条原始记录,再按分钟分组求平均,I/O 和计算都重;而时序库因为数据本来就按时间分块、按列存储,做这种窗口聚合几乎就是顺着时间轴扫一遍,快上两个数量级。
这两个例子的共同点在于:数据形态变了之后,"通用"不仅不再高效,连"正确表达语义"都做不到。专门化存储系统的兴起,就是承认了这件事——不同的数据,该用不同的引擎去伺候。
专门化的核心,不是加一个索引插件,而是从存储格式、索引结构到一致性模型,整套为一种数据形态重写。下面这四类最有代表性。
时序数据库面对的是"按时间追加、按窗口聚合"的数据。它的核心结构是时间分块:把一段时间的数据切成一个块,块内按列存储,再对时间戳和值分别做增量压缩。时间戳是单调的,用前后差值编码能压到极低;值在短时间内通常变化平缓,也能用差分压缩。压缩之外,它还有两个看家本领:一是降采样,把秒级原始数据持续聚合成分钟、小时级,既省空间又加速历史查询;二是保留策略,自动把过期数据删掉或归档。它的一致性通常放宽到最终一致,因为传感器数据本来就允许短暂滞后。
图数据库面对的是"节点和边构成的关系网络"。它的核心结构是邻接表:每个节点的出边紧挨着存在一起,一次内存加载就能拿到这个节点的所有邻居。这带来的是"无索引邻接"——遍历多跳关系时,不需要反复 JOIN 主键,直接按指针跳。图库的一致性模型也跟关系库不同,它更强调单次遍历内的局部一致性,而非全局强一致,因为图的查询天然是局部的。
向量数据库面对的是"高维空间里的点"。它的核心结构是近似最近邻索引,最典型的是 HNSW,一种分层的导航图,上层粗粒度跳跃、下层细粒度收敛,把相似度搜索的复杂度从线性降到对数级。它的"一致性"是一种概率保证——它不承诺返回绝对最相似的那几个,只承诺以某个召回率返回足够相似的。这是向量检索"快"和"准"之间的显式妥协。
搜索引擎面对的是"非结构化文本"。它的核心结构是倒排索引:把文档分词之后,建立"词到文档列表"的映射,查询时直接取包含这些词的文档,再做相关性打分。它的一致性也弱,通常是准实时——写入后要过一个短暂的刷新窗口才能被搜到,换来的是一秒钟能扛几十万次全文查询。
这四类系统的门道各有各的深。时序库的降采样不是简单地把数据平均一下,而是用连续查询在写入流里实时注入计算单元,把秒级数据持续蒸馏成分钟、小时级,同时自动管理各级数据的生命周期。向量库的 HNSW 有两个关键参数——每个节点的出边数和构建时候选集大小,它们直接决定查询延迟、内存占用和召回率这个三角怎么取舍。图库的多跳遍历靠的是指针局部性,用"邻接表一次读全邻居"代替关系库的多次 JOIN。搜索引擎的准实时,则是用"写入后要过一个刷新窗口才能搜到"换来的高吞吐。
把四类系统放在一张表里看,差异就很清楚。它们各自的"强项查询"和"牺牲掉的东西"是对应的。
| 维度 | 时序数据库 | 图数据库 | 向量数据库 | 搜索引擎 |
|---|---|---|---|---|
| 数据形态 | 时间戳加测量值 | 节点与边 | 高维向量 | 文本与文档 |
| 核心结构 | 时间分块、列存、差分压缩 | 邻接表、无索引邻接 | HNSW 等近似最近邻索引 | 倒排索引 |
| 典型查询 | 时间窗口聚合、降采样 | 多跳遍历、路径查找 | 相似度 topK 检索 | 全文检索、相关度排序 |
| 一致性与精度 | 最终一致 | 局部一致 | 概率召回 | 准实时 |
| 典型代表 | InfluxDB、Prometheus | Neo4j | Milvus、Qdrant | Elasticsearch |
⚠️ 常见坑:把专门库当通用库用。拿时序库去存关系数据、拿向量库去存需要精确匹配的业务主数据,都会撞上它"牺牲掉的那部分"。专门库的强项,恰恰是以放弃另一部分能力为代价换来的。
💡 关键直觉:选专门库,本质上是在签一份"数据形态契约"——它承诺把你这一类数据伺候到极致,同时明确告诉你它不擅长别的。签之前,先确认你的数据形态短期内不会变。
注意这四类系统在一致性上不约而同地松了手:它们都放弃了关系库那种全局强一致,换来了各自领域的性能。这不是缺陷,而是精确计算过的妥协——时序数据本来就允许短暂滞后,向量检索本来就是概率问题,图的查询天然是局部的,全文搜索本就不需要事务。理解了这一点,就不会拿 ACID 的尺子去硬量专门库。
专门库好用,但不是免费的午餐。它有三个代价,选型前必须想清楚。
第一个代价是生态窄。关系库有几十年的积累,驱动、工具、监控、人才一应俱全;专门库往往只在一两个垂直领域成熟,出了问题能查的资料、能招的人、能用的周边工具都少得多。
第二个代价是运维面变宽。引入一个专门库,就等于多了一套要部署、升级、备份、监控的系统。一个业务如果同时用了时序、图、向量、搜索四套库,加上原来的关系库,运维负担是五套,而不是一套。这对小团队尤其致命。
第三个代价是数据要搬家、要同步。专门库通常不是唯一事实源,你的核心数据可能还在关系库里,专门库只是它的一个投影。于是你需要一条 ETL 管道,把数据从主库搬进专门库,还要处理两边的一致性和延迟。这条管道本身就是一套要维护的系统。
什么时候值得上?我的判断是看两个信号。一是查询形态是否稳定且专用——如果你的核心场景就是"相似图找图""好友的好友""按窗口聚合",专门库能带来一个数量级的性能提升,那值得。二是数据量是否大到通用库已经扛不住——量小的时候,用关系库硬扛那点性能损失,比维护一套新系统便宜。
反过来,如果业务还在快速变化、数据形态还不确定,或者团队就两三个人,我倾向于先留在通用库里,用它的扩展能力凑合,等形态稳定了再切。过度设计比暂时慢一点更伤。
还有一个折中路线:关系库加扩展。比如 PostgreSQL 加上向量检索扩展、时序扩展之后,也能在一个库里同时做事务和一部分专用查询。这条路的好处是少一套运维,坏处是性能天花板比原生专门库低一截。如果你的专用查询还不重,这条路往往是最务实的起点。
到这里,第 6 章的三块拼图就齐了:云原生管规模,内存库管延迟,专门库管形态。它们共同回答了一个问题——当负载变了,系统该怎么跟着变。下一章我们回到地面,聊怎么用基准测试和监控去衡量、去调优一个真实系统。