# ADR-004：第 4 章物理模型暂不分区

- 状态：已接受
- 日期：2026-07-29
- 适用版本：`ch04-v1`
- 复查章节：第 26 章“分区表生命周期”

## 背景

`shop.sales_order`、`shop.sales_order_item` 与 `shop.payment` 都可能随业务增长，但当前教学样本没有体量、保留期、维护窗口或真实查询计划证据。订单号和支付提供商引用目前要求全局唯一，明细与支付又通过外键引用订单。

## 决策

第 4 章的 v1 模型保持普通表，不为“将来可能很大”预先分区。以下任一条件被真实证据满足时才重新评估：

1. 表或索引已经大到单表维护窗口无法接受；
2. 数据有明确、稳定且可按分区键执行的整批过期/归档策略；
3. 代表性查询使用分区键，并由 `EXPLAIN (ANALYZE, BUFFERS)` 证明裁剪收益；
4. 写入、备份、恢复或冷热分层目标不能再由普通表满足。

复查材料至少包括：按月增长率、关系与索引体积、保留期、最慢查询样本、候选分区键、分区数量上限，以及一次迁移/回退演练。

## 主要理由

如果按 `placed_at` 对订单分区，PostgreSQL 要求分区表上的主键或唯一约束包含全部分区键。于是当前的 `PRIMARY KEY (order_id)` 与 `UNIQUE (order_no)` 不能原样保留；把 `placed_at` 加入键，又会迫使明细和支付携带并引用这一时间值。空的草稿时间、全局订单号唯一性、外键形状和路由接口必须一起重做。

预先分区还会增加建分区、索引、统计信息、约束验证、备份恢复和故障排查的对象数量。没有生命周期或裁剪证据时，这些是确定成本，而收益只是猜测。

## 后果

- 当前 DDL 更短，全局唯一键与外键语义直接、可验证；
- 达到触发条件后需要一次受控的在线迁移，而不是简单执行 `ALTER TABLE ... PARTITION BY`；
- 应用接口不得把当前物理表是否分区当成业务契约；
- 第 26 章必须用生产量级样本重新验证本决定，并记录继续保持普通表或转为分区表的证据。

## 否决的替代方案

- **立即按月分区**：没有保留期、体量和裁剪证据，且破坏当前全局唯一键形状；
- **只分区明细或支付**：仍会引入复合引用键和跨表生命周期不一致；
- **取消数据库唯一性以换取分区**：把可声明的不变量移交给并发下更脆弱的应用检查，不接受。
