数据库设计基础

skillgohub.com 中文指南 | 中文版

数据库设计基础

一个糟糕的数据库设计,是一笔你付一辈子的税。想想一张把客户地址存成单个逗号分隔字符串的购物表。它上线第一天是好的、帮你省了一次 join、也过了代码评审。一年多后市场部要"某个城市的全部客户",你发现唯一能答的办法是对几百万行做一次 LIKE '%城市%' 全表扫描。这条查询现在要四秒,DBA 建了个只能将就用的索引,高峰时段 App 就卡死。这就是跳过数据库设计真正的代价:不是一次大失败,而是一千个小失败,每一个都在悄悄侵蚀性能、烧掉无数工程师工时。

好的数据库设计不是用聪明工具、也不是背第三范式定理证明。它是一小撮结构性决策——怎么把数据拆成表、怎么衔接,以及怎么为增长做规划——决定你未来查询是轻松还是折磨。本指南从"成本与痛苦"的视角讲基础:哪些设计选择能避免坑、哪些模式能规模化、以及怎么识别一个迟早来向你索债的设计。

忽略规范化的代价(以及过度规范化的代价)

规范化名声不好,因为新手要么完全无视它,要么虔诚到把每条查询都变成六表 join。真相是务实的。规范化的目标是避免三种具体的失败模式:重复数据各说各话、因为依赖数据还没出现而插入失败、以及为改一个事实要动很多行。

Database Design Basics - featured image

但规范化不是免费的。每多一张表就多 join,join 花时间也增加查询计划复杂度。务实规则:规范化到消除真实完整性风险为止,然后选择性地反规范化——而且只有在测过那条确实有需要的查询之后。成熟系统是刻意做这笔权衡的;不成熟的系统是被动地绊进去的。

选对键

键是关系的主干,而"自然键 vs 代理键"之争是很多设计很早就走偏的地方。对多数系统的最佳实践,短版本是:

Database Design Basics comparison and review

一个经典错误:用邮箱给 users 表做键,然后再支持"修改邮箱"功能。现在你在更新一张被十张表引用的主键——级联、失效引用、噩梦级迁移纷至沓来。稳定的代理键加上邮箱唯一约束,安全与灵活兼得。

关系、join,以及每个设计者必须懂的类型

关系定义表如何连接,搞对了就能从"清爽的查询"和"维护迷宫"之间分出胜负。基础类型很简单,但人们还是会搞错:

Database Design Basics step by step guide

多对多是最容易糊弄过去的地方。"一个产品可属于多个分类、一个分类又有多个产品"的那一刻,你就需要第三张表把它拆成两对"一对多"。跳过连接表、试图在分隔列里存分类 ID,就是换了个皮的同款逗号分隔陷阱,在查询压力下会以同样的方式崩掉。

设计选择如何决定你的存储和迁移成本

很少有人真去算数据库设计里的钱,但你今天的选择决定了明天的运维账单。两个都通过同一套单元测试的设计,在规模化后的存储和查询成本上可能差一个数量级:

Database Design Basics cost and pricing analysis

这些在第一天都不算"错",但每一项都是复利式成本。你要是做数据量和抽取流程要紧的系统,设计成本会比你想的更快变成拦路虎;想提前把数据用起来的,可以先读一篇AI 数据分析,或先补数据分析基础,都有助于你想清楚哪些查询才真的值钱。

按真实权衡对比主流数据库

选数据库是个披着工具决策外衣的设计决策。不同引擎强制不同的一致性、扩展和查询权衡,要对准你的真实负载来选,而不是图省事。

Database Design Basics tools and features overview
平台/数据库核心特性价格参考
PostgreSQLACID、丰富数据类型、JSONB、强开源生态、出色索引自托管免费;托管云约每月 ¥108–144 起
MySQL应用广泛、复制成熟、兼容多数 Web 应用、运维简单自托管免费;托管约每月 ¥72–144
SQLite零服务器内嵌库、单文件存储、适合小应用和本地工具免费,随附
MongoDB文档模型、灵活 schema、水平扩展、适合缺乏严格关系的数据Atlas 有免费层;付费集群约每月 ¥400 起
Amazon DynamoDB全托管 NoSQL、无服务器、规模化亚毫秒读取按用量付费,免费层 25GB/25 RCU+WCU
MSSQL Server企业级特性、强 BI 集成、Windows 生态支持Developer/Express 免费;Standard 按核心授权

2026 年一个合理的默认:多数新关系型负载用 PostgreSQL(性价比最高),已有运维经验或极简 App 用 MySQL,原型和内嵌用 SQLite,只有在数据确实抗拒固定 schema 时才用 MongoDB 这类文档库。超大规模时 DynamoDB 很亮眼,但你要用更陡的学习曲线和最终一致性的惊喜来付这笔"灵活"。

为你会真正写到的查询来设计

数据库设计和查询规划是同一门手艺。把领域建模得完美却对抗每条常见查询的设计,是个生产力黑洞。务实的设计师会从热查询倒推来设计:

这就是为什么懂数据库管理基础对设计者也重要——"我怎么组织数据"和"我怎么查询维护它"之间的实操重叠,正是多数真实收益所在。同样的道理也适用于日常管理数据库的习惯:备份、迁移、监控,全都在你设计的 schema 之上跑。

索引入门:多数课程一笔带过的设计能力

索引是设计工具,不是事后的性能补丁。如果觉得索引设计是另一回事,那共同主线是:你对列、键和查询模式的决定,决定了哪些索引才说得通。几条对多数设计都适用的默认:

这些模式如果觉得抽象,它们直接对应数据库索引基础背后的纪律,能把一条拖沓的查询变成常见情况下的表查找。

建立有效设计原则,纠正孱弱的设计习惯

抛开机制,糟糕的数据库设计通常是糟糕的思考换了个皮。同样的认知错误反复出现:给文档/UI建模而不是给领域建模、假设数据永远不会增长、以及为了漂亮范式而牺牲实用查询。最强的纠正是用一小撮耐用原则,而不是记边缘用例。让你的核心实体保持稳定、让派生数据被计算或缓存而不是冗余存储、偏好显式外键而非反规范化副本,并且始终问"这行变成几百万行时会怎样?"——这些原则,在讲到数据库设计原则的资料里都讲透了。它们能在绝大多数失败浮出成凌晨 4 点事故之前就拦住它们。

糟糕设计悄悄逼你掏钱重做的那一刻

有个没人提醒新手注意的模式。一个用得很少的内部工具,带一个逗号分隔城市列或文本型日期,顺顺当当跑了两年。然后某次集成或某个新功能试图去查它,突然那套"还行"的架构变得挪不动了。在这种压力下重做,意味着冻结新功能、一次高风险迁移、以及团队要重新学一遍他们原本信任的 schema。修设计缺陷最便宜的时刻永远是今天,趁数据还小、表还少。本指南不需要你有先见之明——只需要你在开头花上几分钟的纪律,以及愿意对"现在省我一小时、一年后坑我一个月"的捷径说不。

延伸阅读: 和 MLOps 基础

常见问题

新手设计第一个 schema 最大的错误是什么?

跳过规范化、把关联数据存成可分隔字符串。存"红、蓝、绿"或一串 ID 的列好写却几乎没法好好查询——它没法有效用索引,每个过滤条件都变成扫描。哪怕只是给多对多关系加一张简单的连接表,几周内就能在查询速度和数据完整性上回本。

应该总是用 UUID 做主键而不是自增整数吗?

不总是。自增整数紧凑、快、递增,最适合大多数单区域关系型应用。你会需要 UUID 的场景是:要合并多个来源的数据、要跨机器分布写入、或想避免泄露记录数量。代价是索引体积和插入性能,所以按你的分布需求选,而不是跟风。

什么时候可以反规范化、存重复数据?

只有在你测出确有真实、反复出现的查询值得为它买单之后才反规范化,并且要把重复控制住。常见类型是预计算聚合(比如订单总额)和"join 成为瓶颈"的重读查询。规则是:反规范化字段应当是派生并被刻意刷新的,不能让它们漂移、与事实源矛盾。

只是做个小内部工具,数据库设计还要紧吗?

要,而且正因为小工具会变大,它才格外要紧。你第一周写的 schema,就是第十二个月你天天要查的 schema,在用户依赖它时再去返修才是最贵的部分。现在花一小时做一次轻量规范化、加一个稳定代理键,将来就能省一次痛苦的迁移——哪怕这个工具永远做不大。

新项目怎么在关系型和非关系型(NoSQL 文档库)之间选?

除非有具体理由,否则先选关系型(PostgreSQL 是很强的默认)。关系型数据库强制完整性,擅长灵活查询和 join,这是多数产品需要的。文档库则在数据确实抗拒固定 schema、你从设计上就要水平扩展、或访问模式纯粹按文档键来命中等情况下才说得通。

📌 Pinterest 🐦 Twitter 📘 Facebook