04 数据库与索引¶
难度:中级|前置:系统思维|目标:从查询模式理解表、索引、事务和分页
数据库首先保存业务事实¶
关系数据库适合保存:
- 有明确结构和约束的数据;
- 需要事务的数据;
- 需要长期追溯的数据;
- 多种条件组合查询的数据。
Redis 很快,但不能因此把关键业务事实只放 Redis。
表设计从实体和关系开始¶
设备系统中常见实体:
每张表都要问:
- 主键是什么?
- 哪些字段必须唯一?
- 哪些状态变化需要历史?
- 删除是物理删除还是逻辑删除?
- 多租户条件是否始终存在?
索引不是“给常查字段都加上”¶
索引的价值由实际查询决定:
可能需要围绕 (tenant_id, status, id) 设计联合索引。字段顺序与等值过滤、范围条件和排序有关。
索引代价:
- 占磁盘和缓存;
- 插入更新需要维护;
- 太多索引会降低写入性能;
- 低选择性字段单独建索引未必有价值。
用 EXPLAIN 验证¶
不要凭感觉说“用了索引”。观察:
- Seq Scan 还是 Index Scan;
- 估算行数与实际行数差异;
- 过滤掉多少行;
- 排序是否额外发生;
- 总耗时和 buffer 读取。
优化流程:
事务解决什么¶
事务把多个数据库操作组织成一个一致的业务单元。ACID 并不意味着跨外部系统也自动一致。
例如:
这不能靠单个数据库事务完全解决,通常需要 Outbox、重试和幂等。
分页¶
OFFSET¶
简单,适合较浅页面,但偏移很大时数据库仍需跳过前面的行。
游标分页¶
适合大数据量连续翻页,但需要稳定排序键,不能随意跳到任意页。
自测¶
- 为什么不能给所有字段都加索引?
- 联合索引顺序为什么与查询有关?
- 数据库事务为什么不能自动保证邮件只发一次?
- OFFSET 和游标分页分别适合什么场景?
完成标准¶
- 能从一个真实 SQL 推导候选联合索引
- 能解释索引的读写取舍
- 能说出 EXPLAIN 至少四个观察点
- 能区分数据库事务和跨系统一致性
延伸阅读:PostgreSQL 当前官方文档
下一单元:Redis 数据结构与选择