
一个你每天都在用但可能从未认真想过的问题你打开手机相册按拍摄时间查找照片打开聊天软件翻出几个月前的一条消息打开浏览器找到昨天访问过的网页。这些数据被存在哪里应用又是怎样把它们找出来的答案并不只有一种照片原文件可能保存在文件系统或对象存储中拍摄时间、文件路径等元数据可能保存在数据库里同一个应用也可能同时使用本地数据库、缓存和远端服务。不过在这些日常软件背后有一个非常常见的名字SQLite。SQLite 是一个嵌入式数据库引擎。它以库的形式运行在应用进程中应用调用它就能查询和修改数据不必单独启动一个数据库服务器。SQLite 官方介绍将它概括为进程内、零配置、支持事务的 SQL 数据库引擎。它究竟有多常见根据 SQLite 官方的部署说明Android、iOS 和多种主流浏览器都使用了 SQLite。官方推测活跃的 SQLite 数据库可能超过一万亿个——这是基于设备数量和使用情况的估算并非逐个统计得出的精确数字。这里还要区分两个容易混淆的概念数据库被组织和保存起来的数据例如订单、用户和账户记录。数据库管理系统DBMS负责管理这些数据的软件例如 SQLite、MySQL 和 PostgreSQL。日常交流中我们常把两者都简称为“数据库”。这个系列主要讨论后者管理数据的软件内部究竟是怎样工作的图 1两种常见的数据库使用形态。嵌入式强调集成方式并不意味着功能简单。SQLite 的持久化数据库通常以一个主文件保存但事务运行时可能产生日志、WAL 等辅助文件。因此“单文件数据库”不能理解为任何时候都只有一个文件“零配置”也不意味着可以忽略备份和数据管理。参见 SQLite 单文件说明。另一类数据库则作为独立服务运行由多个应用通过连接协议访问。MySQL、PostgreSQL、Oracle 等系统通常采用这种方式。形态不同它们面对的问题却有许多共同之处数据越来越多怎样找到需要的那几条记录两个人同时修改一份数据怎样避免互相覆盖银行转账时怎样避免一边扣了钱另一边却没到账机器突然断电已经提交的数据怎样恢复这些问题会把我们带向索引、查询执行、事务和恢复机制。也要记住订单“不重不漏”这样的业务目标往往还需要应用层幂等设计、约束和重试机制共同配合不能只靠“用了数据库”来保证。这个系列就是带你从“会用数据库”走向“理解数据库”。一、数据库从哪里来三条相互叠加的演进主线数据库不是一开始就长成今天的样子。硬件能力、软件理念和业务需求一直在共同影响它的设计。为了建立直觉我们可以把这段历史分成三条主线。它们不是严格的代际替换新的系统出现后旧的模型和技术仍可能继续发挥作用。1. 从按路径访问数据到追求数据独立性在早期大型机环境中层次模型和网状模型是重要的数据组织方式。层次模型用父子结构组织数据IBM IMS 是典型代表网状模型允许更复杂的连接关系。使用这类系统时程序往往需要沿着预先定义的关系逐步访问记录。这种方式能高效支持已知的访问路径但当查询需求或数据组织方式改变时应用代码也可能需要随之调整。问题于是变成能不能让用户描述想要的数据而不必把访问路径写死在程序里2. 关系模型与 SQL把“要什么”和“怎么取”分开1970 年E. F. Codd 提出了关系模型。对初学者来说可以先把关系理解成由行、列组成的表更关键的思想是让逻辑上的数据组织与底层存储方式尽量分离。随后发展起来的 SQL把这种思想变成了熟悉的查询方式SELECT order_id, amount_cents FROM orders WHERE user_id 42;这段 SQL 表达的是“找出用户 42 的订单号和金额”没有规定一定要扫描整张表还是先走某个索引。数据库会根据索引、统计信息等条件选择执行计划。当然这不表示用户完全不用考虑性能。建什么索引、怎样设计表、查询怎样表达仍然会影响数据库可选择的方案。随着关系数据库的发展查询优化、事务、细粒度锁和多版本并发控制等技术逐步成熟。不同系统采用这些技术的时间和方式各不相同不宜把并发能力的提升归结为某一年统一发生的“从表锁改成行锁”。历史脉络可参见 CMU 数据库课程讲义。3. 大规模数据与云计算围绕不同负载做取舍互联网业务让数据规模、访问量和系统可用性要求不断提高。如何跨机器分片、复制和协调数据成为更突出的工程问题。Google 的三篇经典论文分别发表于不同年份年份工作主要解决的问题2003GFS在大量机器上可靠地存储大规模文件2004MapReduce简化大规模数据的分布式批处理2006Bigtable面向大规模结构化数据的分布式存储这些工作影响了后来的大数据系统和分布式存储设计。但 GFS 是文件系统MapReduce 是计算模型与框架不能把它们都当成数据库产品。这一时期键值、文档、列族等系统受到更多关注NoSQL 成为常见的统称。它们并不是统一采用“放弃一致性换扩展性”的方案事务范围、一致性、查询能力和扩展方式需要看具体系统及其配置。另一条路线是通常被称为 NewSQL 或分布式 SQL 的系统保留 SQL 和关系数据模型并在分布式架构中提供事务能力。它们要解决的难点是跨节点事务、复制和故障处理带来的协调成本。与此同时多核处理器、大内存、SSD 和高速网络改变了系统设计的成本结构使一些技术更有吸引力。但不能据此说列式存储和内存数据库直到这些硬件普及后才成为可能。理解这段演进不必记住所有产品。先抓住一个问题就够了这个设计在优化什么又为此付出了什么代价二、数据库的分类用三个观察角度建立认知地图面对众多数据库产品与其背名字不如先问三个问题数据怎样组织主要处理什么负载系统怎样运行和扩展1. 数据模型数据怎样组织和访问类别或能力核心特征典型代表常见用途关系型用表、关系和约束组织数据通常支持 SQLMySQL、PostgreSQL、Oracle订单、账户、企业业务系统键值型通过键访问值值也可能是复杂数据结构Redis缓存、会话、计数器文档型以文档为主要操作单位字段结构较灵活MongoDB、CouchDB内容管理、商品信息、用户资料列族宽列型以行键、列族等组织数据重视访问路径设计HBase、Cassandra大规模记录存取、特定时序负载图模型以节点和边表达实体关系Neo4j、JanusGraph关系遍历、知识图谱、风控分析向量检索对向量进行近邻搜索Milvus、Qdrant、PostgreSQL pgvector语义检索、相似内容检索、推荐这张表是认识产品的入口不是把产品永远装进某一个格子的规则。例如一个关系数据库也可以保存 JSON 文档、支持全文检索和向量检索。向量检索更适合被理解成一种数据处理能力它不一定要求独立部署一款“向量数据库”。还要避免两个常见误解关系模型不自动等于强一致性。事务隔离、持久化配置和副本读取方式都需要单独考察ACID 也不是关系数据库独有的能力。ACID 中的“一致性”主要强调事务保持数据约束与多个副本何时看到相同数据不是同一个概念。列族数据库不等于分析型列式数据库。前者侧重数据模型及访问组织后者侧重按列组织数据以改善扫描和压缩不能只因为名字里都有“列”就混为一谈。2. 业务负载系统主要在忙什么仍然看同一张订单表可以有两种很不一样的任务。观察点OLTP在线事务处理OLAP在线分析处理典型问题创建订单、修改状态、查询某条订单统计最近一年各地区的销售额常见访问范围少量记录事务通常较短大量记录扫描、连接和聚合较多主要关注单次请求延迟、并发、事务正确性扫描吞吐、计算效率、分析时效性常见存储倾向行存列存为什么会形成这种倾向读取一条完整订单时行存可以把相关字段集中在一起统计销售额时列存可以集中读取金额等需要的列并利用相似数据的压缩和批量处理优势。图 2同样三条订单记录两种典型的数据布局。虚线框分别标示整行访问和金额列扫描。“行存适合 OLTP、列存适合 OLAP”是有用的入门直觉但不是绝对规则。实际性能还取决于索引、执行引擎、数据分布和查询方式。HTAP 则希望在同一套系统中同时支持事务和分析负载。例如一边处理订单一边分析刚刚发生的交易。难点在于分析能多快看到新数据大查询会不会拖慢交易3. 架构特征怎样运行、扩展和运维这一角度最好拆开看避免把不同层面的属性当成互斥选项。问题可观察的特征应用怎样访问数据库嵌入式库或独立的数据库服务数据和工作怎样分布单节点、主备多副本、分片集群等资源怎样交付和管理自建、云托管、存算分离、自动伸缩等几个关系尤其值得记住复制与分片解决的问题不同。复制通常侧重冗余、可用性或读扩展分片把数据分散到不同节点。多副本并不自动带来写入能力的线性增长。云托管不等于存算分离。数据库可以运行在云上同时仍保持较紧密的计算与存储绑定。分布式不等于云原生。分布式系统可以自建云服务也可能提供单节点数据库。因此更完整的描述是“这是一个采用关系模型、主要处理 OLTP 负载、使用分片与多副本的托管数据库服务。”这些属性可以叠加不需要争夺同一个分类位置。三、如何看懂今天的数据库格局初学数据库时很容易被排行榜吸引谁排第一谁上涨最快现在应该学哪一个排行榜可以帮助我们发现值得关注的产品但要先理解它在测量什么。例如DB-Engines 的排名方法综合了网站提及、搜索兴趣、技术讨论、招聘等信号衡量的是相对流行度。它并不直接统计安装数量也不是性能测试或市场收入排名。因此得分下降不能直接证明某个数据库的技术衰退、商业策略失败或某个部署市场必然萎缩得分上涨也不能证明它适合你的业务。更有帮助的观察方式是把产品放回它要解决的问题中通用业务数据管理看事务、约束、查询能力、工具和生态。分析与数据平台看扫描、聚合、数据接入和计算资源管理。专门的访问需求看缓存、图遍历、全文检索或向量检索等能力。大规模与高可用需求看分片、复制、故障恢复和跨地域协调的代价。这些方向会交叉。产品也会不断扩展能力。对学习者来说先理解原理再拿具体负载观察实现差异比记住某个月的排名更有用。四、值得关注的技术方向新需求老问题1. 向量检索把“找相同”扩展到“找相似”传统数据库当然不只支持精确匹配它们还可以做范围查询、全文搜索等。向量检索增加了另一种能力在向量空间里寻找接近的对象。通常先由嵌入模型把文本、图片等内容编码成向量再用距离或相似度衡量它们的接近程度。对于合适的模型“表达不同但语义相近”的内容可能落在相近的位置。数据库负责存储、索引和检索向量内容如何被编码主要取决于嵌入模型。也就是说数据库不会仅凭“存了向量”就自动理解语义。这也是 RAG检索增强生成中一种常见的检索方式先找相关资料再把资料交给语言模型辅助回答。图 3图中把检索库画成一个逻辑组件实际系统也可能分别保存向量、文本和元数据。RAG 并不要求一定使用向量检索。实际检索还可能结合关键词、权限过滤和重排序。使用近似近邻索引时也需要在速度、内存和召回率之间取舍。RAG 能提供外部依据但不会自动消除幻觉资料可能过期检索可能漏掉关键片段模型也可能误用材料。这项能力既可以来自专门的向量系统也可以集成到已有数据库中。例如pgvector为 PostgreSQL 提供精确和近似近邻检索允许向量与其他业务数据一起管理。2. 多模型与多模态名字相近含义不同多模型指支持多种数据组织或查询方式例如关系表、文档、图和向量。多模态指处理不同形态的内容例如文本、图片、音频和视频。一个系统可以同时具备两者也可能只具备其中之一。把关系、图和向量能力结合起来主要是在讨论多模型而不能直接据此宣称系统具备了多模态理解能力。这类融合的价值在于让结构化条件、实体关系和相似性检索更方便地协作。但是否更快、更准确需要在明确的数据集、硬件、基线和指标下验证不能只用一个“提升多少倍”的数字概括。3. HTAP让新数据尽快进入分析业务不总能等待第二天的离线报表。例如风控希望尽快识别异常交易运营希望及时看到活动效果。HTAP 希望缩短事务数据进入分析的路径。一些系统会结合行存与列存或采用不同的执行资源来处理两类负载。需要继续追问的是数据同步存在多少延迟分析读取哪个时间点的数据资源隔离怎样实现这些都取决于具体架构不能只凭“支持 HTAP”就推断分析永远实时、也不会影响交易。4. 执行引擎怎样减少处理每条记录的开销传统的逐元组迭代执行便于组合算子但也可能产生频繁的函数调用和解释开销。向量化执行让算子一次处理一批数据编译执行则可以把部分查询逻辑转换成更紧凑的可执行代码。两种方法可以结合使用并不存在所有查询都适用的唯一赢家。特别注意这里的“向量化执行”指批量处理记录与前面的“语义向量检索”不是同一个概念。5. 存算分离与 Serverless更灵活地管理资源存算分离把计算和存储的生命周期、扩展方式进一步解耦使它们可以更独立地调整。代价则可能包括远程访问延迟、缓存一致性和额外的数据传输。Serverless 数据库服务通常进一步封装容量管理和自动伸缩但具体的计费单位、最低容量、唤醒延迟和扩容速度因产品而异。它不等于没有服务器也不保证任何负载下都更便宜这些方向最终仍在回答熟悉的问题怎样更快地访问数据怎样协调并发怎样处理故障以及怎样控制成本。五、这个系列会带你学什么这个系列以 CMU 15-445/645 数据库系统课程的知识体系为主线结合《Database System Concepts》《数据库系统概念》逐步拆解数据库内部的工作过程。你可以先把它想象成一条 SQL 的旅程图 4用于学习的简化分工图。实际系统会合并或拆分模块并非所有查询都会经过所有组件或产生磁盘 I/O。第一季先理解单机数据库的基本骨架主题我们要讲清楚的问题存储与缓冲池数据怎样组织成页为什么有内存还需要管理磁盘 I/O索引哈希与 B 树各自擅长什么索引怎样支持范围查询查询执行排序、聚合、连接算法怎样工作什么时候会用到外部存储查询优化优化器根据什么选择计划估计错了会怎样事务与并发ACID 分别约束什么锁、MVCC 与隔离级别怎样配合日志与恢复WAL 怎样帮助恢复提交、刷盘和持久性是什么关系分布式入门从一台机器到多台机器增加了哪些协调与故障问题B 树是常见的重要索引结构但并不是任何场景的默认答案。恢复机制也需要结合存储可靠性和配置理解不能简单等同于“任何故障下都不会丢数据”。这些边界后续文章会逐步展开。第二季再讨论现代系统的取舍参考 CMU 15-721 高级数据库课程及相关资料进一步讨论内存系统、列存、向量化与编译执行、高级并发控制以及云架构、HTAP 和向量检索。这里借鉴的是课程的知识结构并不意味着文章顺序和主题与某一学期的课程安排完全一致。每篇文章围绕一个核心问题展开用示意图帮助建立直觉再通过适合该主题的小例子或实验验证理解。涉及具体产品时会说明实现背景避免把某一个系统的做法写成所有数据库的通用规则。我希望写出的不是课程笔记的翻译而是“我学完之后怎样把这件事讲清楚给你听。”六、怎样阅读这个系列如果你会写基本 SQL并且对“数据库为什么这样工作”感到好奇这个系列就适合你。后端开发者、计算机专业学生以及准备数据库方向面试的读者都可以沿着这条主线阅读。如果你还没有编程和 SQL 基础可以先补齐基本查询、表和主键的概念。本系列也不会替代某一款数据库的安装、运维或使用手册。每篇尽量独立可读但第一次阅读建议按顺序。不要急着记术语先抓住三个问题这个机制要解决什么问题如果没有它会发生什么它换来了什么又付出了什么下一篇预告下一篇我们从一个最基本的问题开始你写下一行 SQL按下回车数据库到底经历了什么[下一篇01]数据库内核手记 01一条 SQL 从输入到返回经历了什么我们会沿着解析与绑定、查询优化、查询执行和存储访问的路径走一遍查询的生命周期并解释为什么同一条 SQL 在不同条件下可能采用不同的执行计划。如果你对某个主题特别感兴趣欢迎在评论区告诉我。你的反馈会帮助我调整后续文章的例子和讲解重点。