跳转至

新增电话本数据库可行性分析

分析日期:2026-02-14

所属阶段:Phase 1.5(数据基础增强) 前置条件Phase 1 数据链路打通 部署完成 相关文档产品闭环分析 — GAP 7 · SMS 持久化 · 数据库迁移分析

背景

当前系统有 4 个主要数据存储,但没有一个以客户为中心的统一数据库

现有数据库 主键 存的是什么 电话格式
call-analysis telephonySessionId 单次通话记录 + AI 分析 E.164 (+17328561597)
LeadTracking-v2 {leadEmail}#{receivedAt} 单次线索表单提交 E.164 (+17328561597) — Phase 1 后统一
studio-Cache cacheKey SMS 临时缓存 E.164
S3 路径 录音文件

核心问题:这些表记录的都是事件(一次通话、一次提交、一条短信),而不是。系统目前只能在查询时通过电话号码临时关联,没有持久的客户档案。

缺什么

缺失能力 影响
没有客户画像 同一个人打了 5 次电话、提交了 2 次表单、发了 3 条短信,系统不知道这是同一个人
无法存客户分级 产品设计中的 A/B/C/D 分级策略(见 product/customer-segmentation.md)没有字段存放
去重困难 同一个人换了号码或用不同邮箱提交表单,无法识别
格式不统一 通话用 E.164,线索用 10 位数字,关联时需要格式转换

2. 代价

2.1 开发成本

步骤 工作量 难度
CDK 创建 PhoneBook + EmailMapping + Alias 三张表 1 天
callytics-infrastructure 中增加通话→PhoneBook 写入 2 天
lead-tracking 中增加线索→PhoneBook 写入 2 天
studio-api 中增加 SMS→PhoneBook 写入 1 天
studio-api 新增 PhoneBook CRUD API(4 个端点) 3 天
历史数据回填脚本 2 天
去重逻辑(电话+邮箱双重匹配) 2 天
合计 约 13 天(2-3 周)

2.2 基础设施成本

项目 月成本估算
DynamoDB PhoneBook 表存储 ~$0.25(几千条记录 ≈ 几 MB)
DynamoDB EmailMapping 表 ~$0.10
DynamoDB Alias 表 ~$0.05(极少记录)
GSI(4 个索引)写入成本 ~$1-3
Lambda 执行增量 ~$0.50(每次写入多一个 upsert)
月总增量 ~$2-5

2.3 运维成本

  • 新增 3 张 DynamoDB 表的监控告警
  • 去重逻辑复杂度增加了调试难度
  • 三个仓库(callytics-infrastructure、lead-tracking、studio-api)都需要改动,联调成本较高

3. 收益

收益 说明
客户 360 视图 一个页面看到某客户的所有通话、线索、短信、分级、备注
客户分级落地 A/B/C/D 分级策略终于有字段存放,产品设计可以落地
智能去重 电话+邮箱双重匹配,同一个人不同渠道的互动自动归集
数据关联 通过 E.164 标准化,统一电话号码格式,消除跨表关联障碍
为后续功能铺路 自动分级、客户标签、批量操作、数据导出等功能的基础
减少 API 查询 客户基本信息直接从 PhoneBook 读取,不再需要跨多表拼接

4. 重要性

非常高。PhoneBook 是系统从"事件驱动"演进到"客户中心"的关键一步。

  • 产品层面:客户分级策略(product/customer-segmentation.md)已设计完成,但没有数据库存放
  • 技术层面:解决了跨表关联的核心痛点,是后续所有"以客户为维度"功能的基础
  • 业务层面:健身房需要知道"这个人是谁",而不仅是"发生了什么事件"

5. 紧迫性

。建议作为数据库改进计划中的第一优先级。

时间因素 评估
当前是否有生产问题? 有——无法按客户维度查看互动历史,用户体验差
是否阻塞其他计划? 是——客户分级、360 视图、报表统计都依赖它
是否有外部截止日期? 无,但新客户持续进入,越晚做损失越多历史归集数据
依赖关系 无硬依赖,可独立实施;SMS 持久化可后续补充

6. 风险分析

风险 概率 影响 对策
去重逻辑错误导致客户合并 保守策略:不确定时创建新记录;提供手动合并入口
电话号码格式标准化遗漏 统一使用 libphonenumber 库;对非标号码(9位、国际)单独处理
三个仓库联调困难 先用 callytics-infrastructure 单点验证,确认后再扩展到其他仓库
历史回填数据量大导致超时 分批回填,每批 100 条,用 SQS 控制速率
国际号码处理不一致 短期限定 +1(北美号码),国际号码标记为待处理
一人多号场景的别名表维护 通过邮箱匹配触发,场景少但需要正确处理

总体风险:中。主要风险在去重逻辑的正确性,建议采用保守策略(宁可多创建、不错误合并)。

7. 实施计划

7.1 表结构设计

PhoneBook 主表PhoneBook-{env}):

字段 类型 说明 必填
phone String (PK) E.164 格式 (+17328561597),全局唯一
firstName String
lastName String
displayName String 显示名(firstName + lastName
emails String Set 关联的邮箱地址列表
grade String 客户分级:A / B / C / D / ungraded

关于客户分级

产品闭环分析的 debate 结论是:短期用 Hot / Warm / Cold 三级标签(AI 自动计算),长期可考虑 A/B/C/D 手动分级。PhoneBook 的 grade 字段预留了两种模式的兼容性——值域为 hot / warm / cold / A / B / C / D / ungraded,Phase 2 先实现 Hot/Warm/Cold 自动计算。

| gradeUpdatedAt | String | 分级最后更新时间(ISO 8601) | 否 | | source | String | 首次来源:lead / inbound_call / outbound_call / sms / manual | 否 | | leadTypes | String Set | 线索类型集合 | 否 | | tags | String Set | 自定义标签(预留扩展) | 否 | | notes | String | 备注(预留扩展) | 否 | | firstSeenAt | String | 首次出现时间(ISO 8601) | 是 | | lastSeenAt | String | 最后活动时间(ISO 8601) | 是 | | callCount | Number | 通话次数(冗余计数) | 否 | | leadCount | Number | 线索提交次数 | 否 | | smsCount | Number | 短信条数 | 否 | | orgId | String | 所属组织 ID | 是 | | siteId | String | 所属门店 ID | 否 |

GSI 索引

索引名 分区键 排序键 用途
orgId-lastSeenAt-index orgId lastSeenAt 按组织查询客户,最近活跃排前
orgId-grade-index orgId grade 按组织查询某个分级的客户
siteId-lastSeenAt-index siteId lastSeenAt 按门店查询客户
email-index ⚠️ 需用独立 EmailMapping 表实现(见下方说明)

辅助表

  • PhoneBook-EmailMapping-{env}(PK=email → phone):邮箱反查
  • PhoneBook-Alias-{env}(PK=aliasPhone → primaryPhone):号码别名

7.2 去重策略

新数据进来(Lead / 通话 / SMS)
提取电话号码,标准化为 E.164
查 PhoneBook 表:该号码存在?
    ├── 存在 → 更新现有记录(合并信息)
    └── 不存在 → 检查邮箱
              查 EmailMapping 表:该邮箱存在?
                    ├── 存在 → 找到已有客户,添加新号码为别名
                    └── 不存在 → 创建新客户记录

7.3 与现有数据库的关系

新增电话本后的数据架构对比

上图为新增电话本前后的架构对比。蓝色线表示通过电话本的客户画像查询路径,黑色线表示直接的简单查询路径。

7.4 实施步骤

阶段 步骤 工作量
第 1 周 CDK 创建三张表 + GSI 1 天
第 1-2 周 callytics-infrastructure 通话写入 PhoneBook 2 天
第 2-3 周 lead-tracking 线索写入 PhoneBook + 去重逻辑 4 天
第 3 周 studio-api SMS 写入 PhoneBook 1 天
第 3-4 周 studio-api 新增 PhoneBook CRUD API 3 天
第 4 周 历史数据回填 2 天

7.5 新增 API

端点 用途
GET /v2/phone-book 分页查询客户列表(按组织/门店/分级筛选)
GET /v2/phone-book/:phone 查询单个客户详情(关联通话 + 线索 + SMS)
PUT /v2/phone-book/:phone/grade 更新客户分级
PUT /v2/phone-book/:phone 编辑客户信息

7.6 开放问题

  1. 国际号码处理:当前存在 9 位和国际号码(如 +447405706909),需讨论是否支持
  2. 号码归属变更:电话号码从 A 客户转给 B 客户(极少见),如何处理
  3. 批量导入:是否需要支持从 CSV 等外部数据源批量导入客户
  4. 隐私合规:存储客户 PII(姓名、电话、邮箱),需确认数据保留策略

8. 结论

强烈推荐实施

维度 评估
开发成本 中(约 13 天 / 2-3 周)
基础设施成本 极低(~$2-5/月)
技术风险 中(去重逻辑需谨慎)
收益 非常高(客户中心化、分级落地、360 视图)
依赖关系 无硬依赖,可独立实施;被客户分级、报表、自动化等功能依赖
  • callytics-infrastructure — 通话分析完成后,写入/更新 PhoneBook
  • lead-tracking — 线索写入后,写入/更新 PhoneBook
  • studio-api — SMS 相关流程中,写入/更新 PhoneBook

第三步:查询 API

studio-api 中新增:

  • GET /v2/phone-book — 分页查询客户列表(按组织/门店/分级筛选)
  • GET /v2/phone-book/:phone — 查询单个客户详情(关联通话 + 线索 + SMS)
  • PUT /v2/phone-book/:phone/grade — 更新客户分级
  • PUT /v2/phone-book/:phone — 编辑客户信息

第四步:历史数据回填

编写一次性脚本,扫描现有 call-analysisLeadTracking-v2 表,生成 PhoneBook 记录。

风险评估

风险 概率 影响 对策
三张新表增加架构复杂度 PhoneBook 是核心表,EmailMapping 和 Alias 只在去重时用到
跨表写入非原子性 先写源表(call-analysis / LeadTracking),再异步 upsert PhoneBook;失败可重试
历史数据回填可能不完整 回填脚本先 dry-run,验证后执行;无法关联的记录标记为 source: unknown
国际号码处理 当前只有美国客户,非 US 号码暂时跳过(记录日志)

开放问题

  1. 国际号码处理:当前 lead-tracking 中存在 9 位(如 613483122)和国际号码(如 +447405706909)。这些号码无法统一加 +1 前缀,需要讨论是否支持国际号码。
  2. 号码归属变更:如果一个电话号码从 A 客户转给 B 客户(极少见),如何处理?
  3. 批量导入:是否需要支持从 CSV 等外部数据源批量导入客户?
  4. 隐私合规:存储客户 PII(姓名、电话、邮箱),需要确认数据保留策略和隐私合规要求。

PhoneBook 是系统架构从"记录事件"到"管理客户"的转折点,建议作为数据库改进的第一优先级立即启动。PhoneBook 不依赖 SMS 持久化——通话和线索数据已足够构建客户画像,SMS 维度可在后续持久化完成后补充。表结构设计已可 1:1 映射到 PostgreSQL contacts 表,未来迁移关系型数据库时无需修改数据模型。