# Data Source Schema 与 DB Table 合并为单一 Schema：本质差异、性价比与选择

---

## 1. 本质上的不同

| 维度 | 当前（两套约定） | 合并后（单一 schema） |
|------|------------------|------------------------|
| **契约数量** | 两个：① Data source 的「标准化输出」契约（handler 的 schema.py）；② DB 的「表结构」契约（model / 建表语句 / migration）。 | 一个：同一份 schema 既约束「Handler 输出」，又约束「表结构」。 |
| **数据流** | API → Provider → Handler（normalize 按 schema 输出）→ **中间形态** → 由 data_manager/service/model 按「表」再写库；中间是否要再做字段映射、类型转换，取决于两边的约定是否一致。 | API → Provider → Handler（normalize 按 schema 输出）→ **同一形态直接写库**；无需「输出 → 表」的二次映射。 |
| **谁在维护「长什么样」** | Handler 维护 schema.py（输出长什么样）；DB 侧单独维护表结构（或 model 默认与表一致）。两处可能不同步。 | 只维护一处：这份 schema 就是「这张表」的唯一定义，Handler 和持久化层共用。 |
| **table_name 的角色** | 当前：config 里配 `table_name`，表示「写到哪张表」；表长什么样由 DB 侧另定。 | 合并后：schema 的名字或绑定关系即表名；schema 即表结构，不再有「另一套表定义」。 |

**一句话**：  
- **现在**：Data source 产出「按 A 约定」的结构，DB 存「按 B 约定」的结构；A 和 B 是否一致，靠人工和隐式约定。  
- **合并后**：A = B，只有一份约定；产出即表结构，写入时不再做「从 A 到 B」的转换。

---

## 2. 性价比（成本 vs 收益）

### 2.1 收益

- **单一事实来源**：加字段、改类型、改必填，只改一处，采集与存储自动一致，减少「handler 能跑但写入报错」或「表有列但 handler 不填」的错位。
- **代码与概念简化**：  
  - 不再需要「为同一张表在 data_manager 再写一套字段/类型」或为「normalized 到 table 的映射」写胶水；  
  - 持久化层可以做成「按 schema 写表」的通用逻辑（如 replace by unique_keys），而不是每个表一套 save 实现。
- **和「per-table data source」天然契合**：每个 data source 对应一张表、一个 schema；kline / daily_basic / cpi / ppi 分表后，每个都是「一小份 schema + 一表」，不再出现「一个宽 schema 对应一张宽表、消费端再按字段子集读」的情况。
- **利于后续 Entity / 类型化**：一个 Entity 类型 = 一个 schema = 一张表，便于做校验、派生、依赖声明。

### 2.2 成本

- **一次性迁移**：  
  - 现有表若与当前 handler schema 不一致（列名、类型、是否可空），需要做一次迁移：要么改表结构对齐 schema，要么在过渡期保留一层「schema → 现有表」的薄映射（仅此一层，且目标仍是最终收束到单一 schema）。
- **必须接受「一 data source 一表」的纪律**：  
  - 不能再「多个 API 合并成一张宽表」而不改表设计；要合并就得先分表（如 price_indexes 拆成 cpi/ppi/pmi/money_supply），再每个一个 schema。  
  - 这与前面「分表降复杂度」的结论一致，本质是顺势而为，而不是额外约束。
- **灵活性收窄**：  
  - 「同一份 API 输出写两张表」或「同一张表由两个 data source 用不同形状写入」会变成需要显式规则（例如主 data source 定 schema，另一个通过映射或扩展表写入）。  
  - 对当前项目而言，这类需求弱，可以接受。

### 2.3 性价比判断

- 收益是**长期、持续**的（少踩坑、少维护、易扩展）；成本主要是**一次性迁移**和**接受一表一 schema 的纪律**。  
- 若已决定走「per-table data source + 分表」，合并 schema 的额外成本很小，收益很大，**性价比高**。

---

## 3. 我的选择：**采用「Data Source 与 DB Table 共用一个 Schema」**

**理由简述**：

1. **与既定方向一致**：已经倾向「一 data source 一表」、kline/daily_basic 与 price_indexes 分表；合并 schema 是把这个方向贯彻到底，而不是再加一套约束。
2. **降低长期心智负担**：改一个字段只改一处、校验一次；新人看「这张表」只需看一份 schema，不必在 handler 与 DB 之间对表。
3. **实现上可渐进**：  
   - 先在新表 / 新 data source 上做到「schema 即表」；  
   - 老表用迁移或一层薄映射逐步收拢到同一 schema，不必一次性改完所有 handler。
4. **放弃的灵活性**（多 API 合并成一张宽表、同表多形态写入）正是当前要减负的部分，放弃它们有利于整体复杂度下降。

---

## 4. 两种方案优劣对比

| 项目 | 当前（Data Source Schema ≠ DB Table） | 合并（Data Source Schema = DB Table） |
|------|--------------------------------------|----------------------------------------|
| **优点** | 输出形态与存储形态可独立设计；适合「先合并多 API 再落一张宽表」等自由写法。 | 单一事实来源；无产出/表结构漂移；持久化可通用化；与 per-table、Entity 对齐；长期维护成本低。 |
| **缺点** | 两处维护易漂移；需要胶水或约定保证一致；宽表 + 字段子集读取增加心智负担。 | 需一次性或渐进迁移；必须接受一表一 schema；「同表多形态写入」需显式规则。 |
| **适合** | 快速试错、表结构经常独立于采集变化、或多种形态写同一表的需求多。 | 表结构相对稳定、希望采集与存储强一致、且愿意遵守「一 data source 一表」的项目。 |

---

## 5. 小结

- **本质差异**：当前是「输出契约 A + 表契约 B」，合并后是「一个契约 A = B」，产出即表结构，写入无需再做形态转换。
- **性价比**：收益大（单一事实来源、代码简化、与分表/Entity 契合），成本可控（一次性迁移 + 遵守一表一 schema），**性价比高**。
- **选择**：**采用 Data Source 与 DB Table 共用一个 Schema**，并配合 per-table data source 与分表推进；老表可渐进迁移。
- **优劣**：合并方案在长期维护、一致性、扩展性上占优，代价是放弃「输出与表结构随意解耦」的灵活性，对当前项目而言该代价可接受。
