DynamoDB 迁移关系型数据库可行性分析¶
分析日期:2026-02-14
所属阶段:远期规划(3-6 个月后评估) 当前建议:短期维持 DynamoDB + PhoneBook,中期引入 Aurora Serverless v2 混合架构 相关文档:PhoneBook 数据库 · Phase Roadmap
现状:DynamoDB 表清单¶
系统当前共有 26 张 DynamoDB 表(下表列出主要的 12 张),分布在 3 个仓库中:
核心业务表:
| 表名 | 所属仓库 | 主键 | GSI 数量 | 记录特征 |
|---|---|---|---|---|
| call-analysis | callytics-infrastructure | telephonySessionId | 11 | 通话记录 + AI 分析结果 |
| LeadTracking-v2 | lead-tracking | {email}#{time} (复合字符串) |
4 | 线索表单提交 |
| studio-Cache | studio-api | cacheKey | 0 | SMS 临时缓存(DynamoDB TTL 10 分钟) |
studio-api 管理表:
| 表名 | 主键 (PK) | 排序键 (SK) | GSI 数量 | 用途 |
|---|---|---|---|---|
| UserConnections | userId | connectionId | 4 | RingCentral OAuth 连接 |
| OAuthStates | stateId | — | 0 | OAuth CSRF 令牌(TTL 10 分钟) |
| StoresV2 | storeId | — | 1 | 门店配置 |
| PhoneNumbers | providerAccountId | phoneNumber | 2 | RingCentral 同步的号码 |
| PhoneStoreAssignments | storeId | phoneNumber | 1 | 号码与门店的多对多映射 |
| UserStore | userId | storeId | 1 | 用户门店权限 |
| SubAccounts | childUserId | — | 1 | 父子账号关系 |
| BlackoutPeriods | storeId | blackoutId | 1 | 门店停业时段 |
| OperatingHours | storeId | sk | 0 | 门店营业时间 |
其他服务表(未在架构文档中详述)¶
| 表名模式 | 数量 | 用途 |
|---|---|---|
ConnectionService-* |
6 | 组织管理、OAuth 连接、子账号关联 |
rc-subscription-prod-* |
2 | RingCentral Webhook 订阅管理和幂等性 |
CallAnalysisMetadata |
1 | 通话分析元数据 |
call-events / call-analysis |
2 | 历史/遗留表 |
client-configurations |
1 | 客户配置 |
文档盲区
ConnectionService 的 6 张表未出现在任何架构文档中。后续需要补充这些表的文档。
S3 存储¶
| 路径 | 内容 |
|---|---|
s3://.../{sessionId}/audio.mp3 |
通话录音 |
s3://.../{sessionId}/transcript.json |
转录文本 |
s3://.../{sessionId}/analysis.json |
AI 分析结果 |
s3://.../{orgId}/prompts/ |
Prompt 配置文件 |
为什么考虑关系型数据库¶
DynamoDB 的优势(保留这些)¶
| 优势 | 说明 |
|---|---|
| 无服务器 | 不需要管服务器、连接池、版本升级 |
| 按需计费 | PAYPERREQUEST,流量低时几乎免费 |
| 与 Lambda 天然集成 | IAM 鉴权,无需密码管理 |
| 高吞吐 | 单表可承受每秒百万级读写 |
| CDK 管理 | 表结构作为代码,版本可控 |
DynamoDB 的痛点(驱动迁移的原因)¶
| 痛点 | 具体表现 |
|---|---|
| 跨表关联困难 | 查"某客户所有互动"需要分别查 call-analysis、LeadTracking、SMS,再在应用层拼接 |
| GSI 爆炸 | call-analysis 已有 11 个 GSI,每增加一个查询维度就要加 GSI,成本翻倍 |
| 复合主键拼接 | LeadTracking 用 {email}#{receivedAt} 拼接字符串做 PK,不直观且难以修改 |
| 无事务跨表 | 往 PhoneBook + call-analysis 同时写入时,无法保证原子性 |
| 分析查询弱 | 无法 JOIN、无法 GROUP BY、无法子查询;统计报表需要全表扫描或预计算 |
| 数据一致性 | 同一个电话号码在不同表中格式不同(E.164 vs 10 位) |
| 模式演进困难 | 修改主键或索引结构需要建新表 + 数据迁移 |
1.3 业务发展带来的新需求¶
随着产品演进,以下需求在 DynamoDB 上实现越来越困难:
- 客户 360 视图:一个页面看到某客户的所有通话、线索、短信、分级、备注
- 复杂报表:按门店 × 时间段 × 客户分级统计通话量、转化率
- 关联查询:找出"过去 7 天有新线索但没有通话跟进的客户"
- 全文搜索:在通话摘要、备注中搜索关键词
- 数据导出:生成 CSV/Excel 报表给健身房经理
2. 代价¶
2.1 方案对比¶
| 方案 | 开发成本 | 月运行成本 | 迁移风险 |
|---|---|---|---|
| 方案一:全量迁移 PostgreSQL | 非常高(2-3 个月) | ~$65-122/月 | 高 |
| 方案二:混合架构(推荐中期) | 高(1-2 个月) | ~$70-130/月 | 中 |
| 方案三:维持 DynamoDB + 优化 | 低(2-3 周) | ~$5-15/月(现状) | 低 |
2.2 方案一:全量迁移 PostgreSQL 的成本¶
开发成本:
| 步骤 | 工作量 | 说明 |
|---|---|---|
| PostgreSQL Schema 设计 | 1 周 | 13 张 DynamoDB 表 → 关系型表 |
| 数据访问层重写(3 个仓库) | 4-6 周 | callytics-infrastructure、lead-tracking、studio-api 全部改 |
| RDS Proxy + 连接管理 | 1 周 | Lambda 必须通过 Proxy 连 RDS |
| 数据迁移脚本 + 验证 | 2 周 | 全量迁移 + 一致性校验 |
| 合计 | 8-10 周 | — |
基础设施成本:
| 项目 | 当前 DynamoDB | Aurora Serverless v2 |
|---|---|---|
| 月基础费用 | ~$5-15(按需) | ~$43-100(最低 0.5 ACU) |
| 存储 | $0.25/GB | $0.10/GB |
| 连接管理 | 不需要 | RDS Proxy ~$22/月 |
| 月总计 | ~$5-15 | ~$65-122 |
2.3 方案二:混合架构的成本¶
开发成本:
| 步骤 | 工作量 | 说明 |
|---|---|---|
| Aurora Serverless v2 部署 | 1 周 | CDK + RDS Proxy + 安全组 |
| DynamoDB Streams → Lambda → PostgreSQL 同步 | 2 周 | 核心业务表同步 |
| studio-api 查询 API 切换到 PostgreSQL | 2-3 周 | 复杂查询走 PostgreSQL |
| 合计 | 5-6 周 | — |
基础设施成本:DynamoDB + Aurora = ~$70-130/月(两套数据库并行)
2.4 方案三:维持 DynamoDB + 优化的成本¶
开发成本:
| 步骤 | 工作量 | 说明 |
|---|---|---|
| 新增 PhoneBook 表 | 2-3 周 | 见《新增电话本数据库》 |
| 预计算报表(DynamoDB Streams + Lambda) | 1-2 周 | 实时统计写入报表表 |
| 合计 | 3-5 周 | — |
基础设施成本:~$5-15/月(现状 + 几美元增量)
3. 收益¶
3.1 各方案收益对比¶
| 收益 | 方案一(全量迁移) | 方案二(混合架构) | 方案三(DynamoDB 优化) |
|---|---|---|---|
| SQL JOIN 关联查询 | 完全支持 | 查询侧支持 | 不支持 |
| 事务一致性 | 完全支持 | 写入侧不支持 | 不支持 |
| 复杂报表(GROUP BY 等) | 完全支持 | 查询侧支持 | 需预计算 |
| 全文搜索 | PostgreSQL tsvector | PostgreSQL tsvector | 需引入 OpenSearch |
| 现有代码改动量 | 全部重写 | 渐进式改动 | 最小改动 |
| 学习曲线 | 高(ORM、SQL、连接管理) | 中 | 低 |
| 成本控制 | 月增 $50-100 | 月增 $55-115 | 月增 $0-5 |
3.2 关系型 Schema 参考(方案一/二通用)¶
-- 客户(电话本)
CREATE TABLE contacts (
phone VARCHAR(20) PRIMARY KEY,
first_name VARCHAR(100),
last_name VARCHAR(100),
grade VARCHAR(1),
source VARCHAR(20),
org_id VARCHAR(50) NOT NULL,
site_id VARCHAR(50),
first_seen TIMESTAMPTZ NOT NULL,
last_seen TIMESTAMPTZ NOT NULL,
created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT NOW()
);
-- 通话记录
CREATE TABLE calls (
session_id VARCHAR(100) PRIMARY KEY,
from_phone VARCHAR(20) REFERENCES contacts(phone) ON DELETE SET NULL, -- nullable: 未知号码的通话
to_phone VARCHAR(20) REFERENCES contacts(phone) ON DELETE SET NULL, -- nullable: 未知号码
direction VARCHAR(10),
duration INTEGER,
start_time TIMESTAMPTZ NOT NULL,
org_id VARCHAR(50) NOT NULL,
site_id VARCHAR(50),
summary TEXT,
category VARCHAR(50),
outcome VARCHAR(50),
grade VARCHAR(1),
staff_name VARCHAR(100),
s3_audio VARCHAR(500),
s3_transcript VARCHAR(500),
s3_analysis VARCHAR(500),
created_at TIMESTAMPTZ DEFAULT NOW()
);
-- 线索
CREATE TABLE leads (
id SERIAL PRIMARY KEY,
phone VARCHAR(20) REFERENCES contacts(phone),
email VARCHAR(255),
lead_type VARCHAR(50),
booked_date DATE,
booked_time TIME,
org_id VARCHAR(50) NOT NULL,
received_at TIMESTAMPTZ NOT NULL,
raw_body TEXT,
created_at TIMESTAMPTZ DEFAULT NOW()
);
-- SMS 消息
CREATE TABLE messages (
message_id VARCHAR(100) PRIMARY KEY,
phone VARCHAR(20) REFERENCES contacts(phone),
store_id VARCHAR(50) NOT NULL,
direction VARCHAR(10),
content TEXT,
sent_at TIMESTAMPTZ NOT NULL,
created_at TIMESTAMPTZ DEFAULT NOW()
);
4. 重要性¶
中。重要但不紧急。
- DynamoDB 目前能满足核心业务需求,只是在复杂查询场景不够优雅
- PhoneBook 表(在 DynamoDB 上)已经解决了最紧迫的"客户档案缺失"问题
- 关系型数据库的价值主要体现在报表和分析阶段,而非当前的功能建设阶段
5. 紧迫性¶
低。建议等业务需求真正推动时再启动。
| 时间因素 | 评估 |
|---|---|
| 当前是否有生产问题? | 无——DynamoDB 性能和可用性均无问题 |
| 是否阻塞其他计划? | 否——PhoneBook、SMS 持久化都可以在 DynamoDB 上实现 |
| 是否有外部截止日期? | 无 |
| 触发条件 | 当出现以下情况时再考虑:(1) 报表需求频繁且复杂 (2) GSI 数量继续膨胀 (3) 多表事务需求增多 |
推荐时间线:
| 阶段 | 时间 | 做什么 |
|---|---|---|
| 短期(1-3 个月) | 现在 | 方案三:DynamoDB 上建 PhoneBook,优化数据模型 |
| 中期(3-6 个月) | 需求驱动 | 方案二:引入 Aurora Serverless v2,DynamoDB Streams 同步 |
| 长期(6-12 个月) | 评估 | 方案一:如果 PostgreSQL 承担大部分查询,考虑全量迁移 |
6. 风险分析¶
6.1 迁移相关风险¶
| 风险 | 概率 | 影响 | 对策 |
|---|---|---|---|
| DynamoDB Streams 同步丢数据 | 中 | 高 | Streams 有 24h 重试窗口;Lambda DLQ 兜底 |
| Aurora 冷启动影响 Lambda 响应 | 低 | 中 | Serverless v2 最低 0.5 ACU,无完全冷启动 |
| Lambda 连接池耗尽 | 中 | 高 | 使用 RDS Proxy;Lambda 并发上限配合连接池大小 |
| Schema 变更困难 | 低 | 中 | 使用 Drizzle ORM migration 管理 |
| 成本超预期 | 中 | 中 | 设置 CloudWatch 费用告警;Serverless v2 按需扩缩 |
6.2 不迁移的风险¶
| 风险 | 概率 | 影响 | 说明 |
|---|---|---|---|
| GSI 持续膨胀 | 高 | 中 | call-analysis 已有 11 个 GSI,每个新查询维度都要加 |
| 复杂查询性能下降 | 中 | 中 | 全表扫描越来越慢 |
| 开发效率下降 | 中 | 低 | DynamoDB 查询模式受限,每个需求都要想 workaround |
6.3 技术栈选型¶
如果决定引入关系型数据库:
| 层级 | 选择 | 理由 |
|---|---|---|
| 数据库 | Aurora Serverless v2 (PostgreSQL) | 与 AWS 生态集成最好;Serverless 按需扩缩 |
| ORM | Drizzle ORM | TypeScript 原生;类型安全;轻量;支持 migration |
| 连接管理 | RDS Proxy | Lambda 必需;自动连接池管理 |
| 数据迁移 | drizzle-kit | Schema 版本管理和迁移 |
为什么不选其他数据库:
| 数据库 | 不选原因 |
|---|---|
| RDS MySQL | PostgreSQL 的 JSONB 更适合存半结构化 AI 分析结果 |
| PlanetScale | 脱离 AWS 生态;额外网络延迟 |
| Supabase | 托管在 AWS 外部;增加外部依赖 |
| CockroachDB | 过度设计;不需要多 region 分布式 |
| MongoDB Atlas | 如果要用 NoSQL,DynamoDB 已经够了 |
7. 实施计划¶
7.1 阶段一(短期,现在):DynamoDB 优化¶
- 在 DynamoDB 上新增 PhoneBook 表(见《新增电话本数据库可行性分析》)
- 不引入新的数据库类型,降低运维复杂度
- 通过 DynamoDB Streams 同步客户活动计数
7.2 阶段二(中期,需求驱动):混合架构¶
DynamoDB (写入源)
↓ DynamoDB Streams
Lambda (转换 & 写入)
↓
PostgreSQL (查询副本)
↓
studio-api (复杂查询走 PostgreSQL,简单查询走 DynamoDB)
迁移到 PostgreSQL 的数据:
| 保留在 DynamoDB | 同步到 PostgreSQL |
|---|---|
| studio-Cache(纯缓存) | contacts(电话本) |
| OAuthStates(短期令牌) | calls(通话记录) |
| UserConnections(OAuth 连接) | leads(线索) |
| OperatingHours(门店配置) | messages(SMS) |
| BlackoutPeriods(门店配置) | user_stores(权限) |
7.3 阶段三(长期,评估):全量迁移¶
- 如果 PostgreSQL 承担了大部分查询,考虑将写入也迁移过去
- 保留 DynamoDB 给纯缓存和短期数据(OAuth、Cache)
- 最终形态:PostgreSQL 为主数据库,DynamoDB 为辅助缓存
8. 结论¶
当前不建议迁移,但应为未来做好准备。
| 维度 | 评估 |
|---|---|
| 开发成本 | 高(方案一 8-10 周 / 方案二 5-6 周) |
| 基础设施成本 | 月增 $50-115 |
| 技术风险 | 中高(数据同步、连接管理、Schema 迁移) |
| 收益 | 高(SQL 关联查询、事务、报表),但当前阶段收益不明显 |
| 紧迫性 | 低——DynamoDB 目前够用 |
行动建议:
- 现在做:DynamoDB 上建 PhoneBook 表,表结构设计兼容 PostgreSQL(1:1 可映射)
- 等信号:当报表查询频繁需要 JOIN/GROUP BY 时,启动混合架构
- 成本底线:DynamoDB ~$5-15/月 vs Aurora ~$65-122/月,确认业务价值能覆盖成本增量