mcpField
D
database-design

database-design

github.com/krzysztofsurdy数据与数据库3644 次安装2 天前更新
代码仓库

关于 database-design

面向应用开发者的数据库设计技能,帮助规划或演进应用架构。内容将表结构选择与访问模式、一致性需求相结合,涵盖数据建模、索引、数据库类型和迁移策略。

主要功能

  1. 01建模实体关系并规范化数据
  2. 02按工作负载选择数据库类型
  3. 03根据查询模式设计索引
  4. 04规划安全的架构演进
  5. 05评估分区与分片

适用场景

  1. 01为新应用设计数据库架构
  2. 02优化常用查询的索引
  3. 03规划生产环境中的架构变更

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/krzysztofsurdy/code-virtuoso --skill database-design

安装后在 Claude Code 中输入/database-design确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/
indexing-strategies.md
migration-patterns.md
modeling-patterns.md

详细介绍

数据库设计

数据库设计决定了数据驱动型应用的长期可维护性、性能和正确性。早期的架构决策很难撤销。每个表、列、索引和约束都应有充分理由,并以访问模式和业务规则为依据。

数据建模原则

从访问模式入手

围绕应用读写数据的方式设计表,而不是围绕领域模型中的实体外观设计。两个问题决定了每项架构决策:

  1. 哪些查询的运行频率最高? 这决定了表结构、索引和反规范化方案。
  2. 数据需要满足哪些一致性保证? 这决定了规范化程度、约束和事务边界。
实体关系
关系实现方式适用场景
一对一在子表中使用带 UNIQUE 约束的外键将很少访问的列拆分到单独的表中,或强制实现恰好一个的语义
一对多子表中的外键引用父表订单与订单项、用户与地址
多对多使用复合主键的联结表标签与文章、学生与课程
带属性的多对多除两个外键外,还包含自身列的联结表包含成绩的选课记录、包含角色的成员关系
自引用外键引用同一张表组织架构图、类别树、嵌套评论
命名约定

统一的命名可避免团队和工具之间产生混淆:

  • 表:使用 snake_case 复数名词(order_items、user_addresses)
  • 列:使用描述其值的 snake_case 单数名称(created_at、total_amount)
  • 外键:<referenced_table_singular>_id(user_id、order_id)
  • 索引:idx_<table>_<columns>(idx_orders_user_id_created_at)
  • 约束:chk_<table>_<rule>、uq_<table>_<columns>、fk_<table>_<referenced>

规范化与反规范化

范式
范式规则违反示例
1NF每列都存放原子值;不存在重复组在单列中存储以逗号分隔的标签
2NF每个非键列都依赖于整个主键在复合键表中,某列只依赖于键的一部分
3NF非键列不依赖于其他非键列同时存储 city 和 zip_code,而邮政编码决定城市
BCNF每个决定因素都是候选键排课表中教室决定楼宇,但教室不是键
何时进行反规范化

规范化可以避免异常,但会增加 JOIN。应有选择地进行反规范化,并且仅在以下情况进行:

  • 读操作繁重的工作负载占主导,且通过性能分析确认 JOIN 开销显著
  • 报表表需要预聚合数据,否则就必须执行开销高昂的查询
  • 缓存计算值可避免每次读取时都重新计算(例如,将 order_total 存储在订单行中)
  • 面向文档的访问需要一次读取整个聚合

安全反规范化的规则:

  1. 始终保留规范化的数据源。反规范化数据是派生缓存
  2. 明确反规范化副本的更新方式和时机(触发器、应用事件、批处理作业)
  3. 监控数据源与副本之间的偏差
  4. 记录反规范化的原因及其服务的访问模式

选择数据库类型

类型优势适用场景
关系型(PostgreSQL、MySQL)ACID 事务、复杂查询、成熟的工具、JOIN数据结构化且存在关联、事务型工作负载、大多数 CRUD 应用
文档型(MongoDB、DynamoDB)灵活的架构、嵌套数据、水平扩展以整体为单位访问的聚合数据、快速演变的架构、按租户隔离
键值型(Redis、Memcached)亚毫秒级读取、简单的数据模型会话存储、缓存、计数器、速率限制
列族型(Cassandra、ScyllaDB)高写入吞吐量、宽行、线性扩展时间序列、IoT 遥测、写入密集型工作负载
图数据库(Neo4j、Neptune)遍历查询、以关系为核心的数据社交网络、推荐引擎、欺诈检测
时序型(TimescaleDB、InfluxDB)针对带时间戳的数据优化、自动分区指标、监控、金融行情数据

只有在不同部分的访问模式存在差异时,才有理由采用多模型持久化(在同一系统的不同部分使用不同数据库)。这并不是逃避深入学习某一种数据库的方式。


索引基础

索引可以加快读取,但会降低写入速度并增加存储开销。每个索引都必须有查询模式作为依据。

索引类型
类型结构最适用于
B-tree平衡树、有序数据等值和范围查询、ORDER BY、大多数通用索引场景
Hash哈希表仅适用于精确等值查找;不支持范围查询
GiST通用搜索树空间数据、几何查询、范围类型、最近邻查询
GIN通用倒排索引全文搜索、JSONB 包含查询、数组成员查询
BRIN块范围索引数据按自然顺序存储的大型表(时间戳、递增 ID)
复合索引设计

复合索引中列的顺序很重要。最左前缀规则意味着,针对 (a, b, c) 创建的复合索引支持按 (a)、(a, b) 或 (a, b, c) 进行筛选的查询,但不支持仅按 (b, c) 查询。

列排序指南:

  1. 等值条件列在前(使用 = 比较的列)
  2. 范围条件列在后(使用 >、<、BETWEEN 比较的列)
  3. 等值条件列中,区分度最高的列在前
覆盖索引和部分索引
  • 覆盖索引:包含查询所需的所有列,因此数据库只需读取索引。使用 INCLUDE(PostgreSQL),或将列添加到索引键中。
  • 部分索引:只为符合条件的行创建索引,从而减少索引大小和写入开销。适用于查询大型表中的小部分数据(例如,WHERE status = 'pending')。

详见 索引策略参考,了解详细的索引类型、EXPLAIN 分析和反模式。


架构演进

架构变更不可避免。关键在于这些变更是否会导致运行中的应用出现问题。

向后兼容的变更(安全)
  • 添加新的可空列
  • 添加新表
  • 添加新索引(某些引擎可能会短暂锁表)
  • 扩大列类型的范围(例如,从 VARCHAR(50) 改为 VARCHAR(100))
破坏性变更(需要迁移策略)
  • 重命名或删除列
  • 以不兼容的方式更改列类型
  • 在包含空值的现有列上添加 NOT NULL 约束
  • 拆分或合并表
扩展-收缩模式

对于生产环境中的破坏性变更,可按以下步骤实现零停机:

  1. 扩展: 在旧结构旁添加新结构
  2. 迁移: 将数据从旧结构回填到新结构,并在过渡期间双写
  3. 切换: 更新应用代码以使用新结构
  4. 收缩: 确认没有任何内容引用旧结构后,将其删除

详见 迁移模式参考,了解零停机策略、回滚技巧和多工具示例。


分区与分片

表分区(单个数据库)
策略工作方式适用场景
范围按值范围拆分行(例如按月)时间序列数据、日志表、归档
列表按离散值拆分行(例如按区域)多租户数据、地理分区
哈希根据某列的哈希值分发行不存在自然范围时实现均匀分布
分片(多个数据库)

分片会将数据分布到单独的数据库实例中。只有在单实例优化(索引、缓存、只读副本)都已用尽后,才使用分片。

分片键选择标准:

  • 高基数:具有许多不同的值,以便均匀分布
  • 出现在大多数查询中:避免对所有分片进行分散-收集
  • 稳定:创建后不会更改的值
  • 无热点:不要按会集中写入的值分片(例如当前日期)

快速参考:常见设计错误

错误后果修复方法
没有外键约束孤立行、数据不一致除非有记录在案的理由,否则始终定义外键
索引过多写入缓慢、浪费存储空间仅为实际查询中 WHERE、JOIN、ORDER BY 使用的列创建索引
存储计算值但未制定刷新策略数据过时、隐蔽的错误对每项反规范化,都定义更新触发器、事件或批处理作业
对会变化的值使用 ENUM 类型每增加一个新值都要迁移架构改用带外键的查找表
以浮点数存储金额舍入误差使用 DECIMAL/NUMERIC,或将金额存储为整数分
缺少 created_at / updated_at 时间戳无法审计,难以调试默认在每张表中添加时间戳列
到处使用通用的 type + type_id 多态模式没有引用完整性,查询复杂先评估 STI、CTI 或独立表

参考文件

参考资料内容
建模模式多态关联(STI/CTI/TPT)、软删除、审计跟踪、时态数据、自引用树、JSON 列
索引策略B-tree/hash/GiST/GIN 详解、复合索引设计、覆盖索引和部分索引、EXPLAIN 分析、反模式
迁移模式基于版本与基于状态的迁移、扩展-收缩、数据迁移、回滚策略、多工具示例

与其他技能集成

场景推荐技能
优化查询性能和缓存performance
设计领域模型和聚合clean-architecture
构建可公开数据库资源的 APIapi-design
测试数据库交互testing

评论

支持 Markdown