# FDW 数据源迁移方案：DWD → Core

> 创建日期：2026-02-24
> 状态：已决策（上线后迭代）
> 关联 SPEC：miniapp-db-foundation

---

## 背景

当前 `miniapp-db-foundation` SPEC 中，FDW 外部表映射的数据源链路为：

```
ETL 库 dwd.dim_* / dws.dws_*
    → app.v_dim_* / app.v_dws_*（RLS 视图，site_id 过滤）
    → 业务库 fdw_etl.v_dim_* / fdw_etl.v_dws_*（FDW 外部表）
```

ETL 六层 Schema 中，`core` 层的定位是"跨门店标准化维度/事实"，是 DWD 层的精简子集。长远来看，小程序读取的维度数据应从 `core` 层获取，而非直接读 `dwd` 层。

## 决策

上线时保持现状（`app` 视图指向 `dwd.*` / `dws.*`），上线后再迭代切换到 `core`。

## 理由

1. Core 层当前仅 7 张表（`dim_site`、`dim_member`、`dim_assistant`、`dim_table`、`dim_goods_category`、`fact_settlement`、`fact_payment`），小程序需要的 11 张 DWD + 24 张 DWS 远超 Core 覆盖范围
2. Core 层字段是精简子集（如 `core.dim_member` 无 `card_balance`、`total_consumption` 等），小程序前期需要 DWD 的完整字段
3. `app` 视图层本身就是抽象层——后端通过 `fdw_etl.v_dim_member` 访问数据，底层视图定义可随时切换，后端代码零改动
4. 上线关键路径是 P0 阶段（基础设施 → 微信配置 → 后端核心功能），Core 层完善属于 P2 范畴

## 迁移路径

### Phase 0：上线前（当前）

按 SPEC 原样执行：
- `app.v_dim_member` → `SELECT * FROM dwd.dim_member WHERE site_id = ...`
- `app.v_dws_*` → `SELECT * FROM dws.dws_* WHERE site_id = ...`
- FDW 通过 `IMPORT FOREIGN SCHEMA app` 映射

### Phase 1：上线后 — 补齐 Core 层表

- 盘点小程序实际用到的维度表，确认 Core 层需要补齐哪些字段
- 对照 DWD 层的 `dim_member`、`dim_assistant` 等，在 Core 层补全小程序所需的业务字段
- 新增 Core 层缺失的维度表（如 `core.dim_member_card_account`、`core.dim_staff` 等）

### Phase 2：上线后 — ETL 填充任务

- 在 ETL Connector 中新增 DWD → Core 的填充任务
- 确保 Core 层数据与 DWD 层保持同步
- 验证 Core 层数据完整性和正确性

### Phase 3：上线后 — 切换视图定义

- 修改 `app` 视图定义，将维度表从 `dwd.*` 切换到 `core.*`：
  ```sql
  -- 修改前
  CREATE OR REPLACE VIEW app.v_dim_member AS
  SELECT * FROM dwd.dim_member
  WHERE site_id = current_setting('app.current_site_id')::bigint;

  -- 修改后
  CREATE OR REPLACE VIEW app.v_dim_member AS
  SELECT * FROM core.dim_member
  WHERE site_id = current_setting('app.current_site_id')::bigint;
  ```
- DWS 汇总表保持不变（它们本身就在 DWS 层，Core 层不涉及汇总）
- 重新执行 `IMPORT FOREIGN SCHEMA app INTO fdw_etl` 同步外部表
- 后端和小程序代码无需任何改动

## 风险与缓解

| 风险 | 缓解措施 |
|------|---------|
| Core 层字段不全导致小程序功能缺失 | Phase 1 先盘点再补齐，确保字段覆盖 |
| DWD → Core 填充任务引入数据延迟 | Core 填充任务纳入 ETL 调度链，与 DWD 同步执行 |
| 切换视图时短暂不可用 | 使用 `CREATE OR REPLACE VIEW` 原子替换，无停机 |
| Core 层数据与 DWD 不一致 | 切换前运行数据一致性校验脚本 |

## 关键设计优势

`app` 视图层是整个方案的"切换开关"：
- 后端只看到 `fdw_etl.v_dim_member`，不关心底层是 DWD 还是 Core
- 切换只需修改视图 SQL + 重新 IMPORT，零代码改动
- 可以逐表切换（先切 `dim_member`，验证通过后再切其他表），降低风险
