Skip to content
知识

/knowledge/database-systems

数据库系统

数据真正栖身之处。每一个仪表板和模型背后,都有一个数据库,让数百万条事实保持正确、一致、可被即时查询——而懂得它如何运作,正是让一名分析师变快的原因。

学于
数据库系统理学学士 · 数据科学核心
时间
墨尔本大学,2019–2022
应用于
贯穿每段分析工作的 SQL
阅读 / 复习
约 15 分钟阅读2026-06-25

模型和仪表板赢得了光彩,但它们全都坐落在一个数据库之上。它是那个不光鲜的基础,让 数百万条事实保持正确、一致、可快速查询——一名懂它的分析师能在几秒内拉出干净的数据, 而别人要为此鏖战数小时。这是基础的「系统」那一半:不是数据的数学,而是大规模存储与 检索它的工程。

我担任过的每一个分析师岗位都运行在 SQL 之上,所以这是一张我时刻在实践的页。这里是 完整的图景——从数据库为何存在,到它们如何在毫秒之间回答一次查询。

01

数据库为何存在

你可以把数据放在电子表格或文件里。但对任何真实的场景,那很快就会崩。一个由数据库管理系统(DBMS)管理的数据库,正是为了解决文件 解决不了的问题而存在:

  • 并发——成百上千的用户同时读写,而不破坏彼此的工作。
  • 完整性——保持数据有效的规则(不会有订单指向一个不存在的客户)。
  • 规模与速度——在毫秒而非分钟内查询数十亿行。
  • 持久性——已提交的数据能在崩溃或断电后存活。

电子表格给不了你这其中任何一项保证。数据库则从根基上被构建,以同时提供这四者。

02

关系模型

占主导地位的设计,其要旨自 1970 年代以来未变,就是关系模型:把数据 存在(关系)中,每一行是一条记录,每一列是一个属性。表与表之间由相连:

  • 一个主键唯一地标识每一行(一个客户 ID)。
  • 一张表里的外键指向另一张表的主键,从而编码一种关系(一个订单的 customer_id 引用 customers 表)。

这个简单的思想——事实存于表中,关系以键引用——足以为几乎任何领域建模,而它的纪律 正是防止那些困扰电子表格的矛盾的原因。

Customersid (PK)nameemailOrdersid (PK)customer_id (FK)totalFK → PK
两张相关的表。每个 Order 都带有一个 customer_id 外键,指向 Customers 表的主键——于是关系只存储一次,没有重复的客户细节。

03

SQL:向数据发问

你用 SQL(结构化查询语言)与关系数据库对话。它的决定性特征是声明式:你描述你想要什么,而非如何得到它。你说 「给我每个区域的总销售额,从高到低排序」,数据库的查询规划器便算出最高效的计算 方式。

SELECT region, SUM(total) AS sales
FROM orders
WHERE order_date >= '2026-01-01'
GROUP BY region
ORDER BY sales DESC;

四个子句在任何地方都承担了大部分工作:SELECT(哪些列)、FROM(哪张表)、WHERE(过滤行),以及——用于汇总——GROUP BY 搭配 SUMCOUNT 这样的聚合函数。 再加上四个写操作(INSERTUPDATEDELETE, 以及用于结构的 CREATE),你几乎就能做任何事。在这里的熟练,是分析师 杠杆最高的单一技能。

04

规范化

你如何把数据拆分到各张表中,影响极大。规范化是组织表以消除冗余、 使每个事实恰好存储一次的过程。其动机是更新异常:如果一个客户的邮箱 被复制进他全部 500 行订单里,改它就意味着 500 次更新——漏掉一次,数据就自相矛盾了。

解决办法是把邮箱在 customers 表里只存一次,并以键引用它。范式(1NF、2NF、3NF)是系统化地做到这一点的一连串规则——大致是:每个单元格一个值、 每一列都依赖于整个键,以及没有任何列依赖另一个非键列。

05

连接(JOIN)

因为规范化的数据住在各自分开的表里,你用一个 JOIN(连接)把它重新 拼起来——按一个键在表之间匹配行。要列出每个订单连同其客户的名字,你在 orders.customer_id = customers.id 上把 orders 连接到 customers。 主要的几种:

  • INNER JOIN——只保留在两张表中都有匹配的行(拥有有效客户的订单)。
  • LEFT JOIN——左表的每一行,右表有匹配处填上匹配、没有处留空 (所有客户,即便是没有订单的)。

连接是 SQL 真正变得富有表达力之处——也是初学者栽跟头之处,通常是不小心让行翻倍 (在一个非唯一键上连接)或丢掉行(本想用左连接却用了内连接)。在脑中描绘出哪些行 能在匹配中存活,就是全部的关键。

06

索引

一个数据库如何在十亿行的草堆里于毫秒间找到一根针?和你在词典里找一个词的方式 一样——你不会读每一页。一个索引是一个独立的、有序的数据结构(几乎 总是一棵 B 树),它让数据库近乎瞬间地跳到匹配的行,而不必扫描整张表。

对十亿行的全表扫描是线性的——时间与表的大小成正比。一棵 B 树索引把它变成大约 log(n) 步:沿树向下几跳,哪怕面对数十亿行。这就是一次查询耗时数分钟与 耗时数毫秒之间的区别。

log(n) 跳,而非 n
一棵 B 树索引。查询从根开始,沿几条分支向下走到目标——对数十亿行也只需寥寥几步,而不必逐一扫描。

07

事务与 ACID

有些操作必须全有或全无地发生。转账要从一个账户扣款、向另一个账户入账——如果系统 在两者之间崩溃,你不能让钱凭空消失。一个事务把若干语句组成一个不可 分割的单元,而关系数据库以 ACID 属性来保证它们:

  • 原子性——要么全部发生,要么全不发生。没有半截的转账。
  • 一致性——数据库从一个有效状态转移到另一个,绝不破坏自己的规则。
  • 隔离性——并发的事务看不到彼此做了一半的工作。
  • 持久性——一旦提交,它就能在崩溃后存活。

ACID 是任何处理金钱、记录,或任何「大致正确」还不够好的系统中信任的基石——而这 正是我所处理过的大多数政府与金融数据。

08

OLTP、OLAP 与 NoSQL

并非所有数据库都为同一种工作而调优,而把存储与工作负载匹配起来是一个真实的设计 决策:

  • OLTP(事务型)——许多小而快的读写;规范化;应用背后的实时系统。 为 ACID 吞吐而优化。
  • OLAP(分析型)——对历史数据的大型聚合查询;常被反规范化进一个采用 列式存储的数据仓库。这正是大多数分析与 BI 实际运行之处。
  • NoSQL——一个家族(文档、键值、图、宽列),它用一些关系保证换取规模 或灵活性,服务于不适合整齐表格的数据。有用,但不是关系模型的默认替代品。

09

它在我工作中的体现

10

60 秒回顾