Files
Web_BLS_Heartbeat_Server/docs/db-guid-pk-and-service-mask-index-plan.md
XuJiacheng 41301f9ce5 feat: 实现GUID主键与service_mask索引改造
- 将主键从自增id改为GUID格式并添加格式校验
- 为service_mask添加表达式索引优化首位查询性能
- 更新相关文档说明改造方案与验证步骤
- 添加统计模块记录数据库写入与Kafka消费量
- 重构Redis心跳协议改用LIST类型存储项目状态
- 修复部署脚本中的服务名称不一致问题
2026-01-17 18:37:44 +08:00

41 lines
2.2 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# GUID 主键与 service_mask 索引改造实施方案
## 目标
-`heartbeat.heartbeat_events` 的主键从自增 `id` 改为 GUID32 位无连字符 HEX 字符串)。
-`service_mask` 的“首位(最低位)判断”新增表达式索引 `idx_service_mask_first_bit`,用于优化常见 bit 查询。
- 说明:你会删除现有数据库,因此不提供在线迁移流程,仅提供可重建的初始化脚本与验证步骤。
## 方案概述
### 1) 主键GUID
- 表字段 `guid` 使用 `varchar(32)` 并设置默认值 `replace(gen_random_uuid()::text, '-', '')`
- 通过 `CHECK (guid ~ '^[0-9a-f]{32}$')` 约束输入格式为 32 位小写 HEX。
- 分区表使用组合主键 `PRIMARY KEY (ts_ms, guid)` 以满足 PostgreSQL 分区唯一约束要求(主键/唯一约束需包含分区键)。
### 2) service_mask 首位查询表达式索引
- 在父表创建索引:
- `CREATE INDEX idx_service_mask_first_bit ON heartbeat.heartbeat_events ((service_mask & 1));`
- 在按天分区创建索引:
- `idx_<partition>_service_mask_first_bit`
## 实施步骤(重建式)
1. 删除旧数据库/旧 schema你将执行
2. 执行建表脚本:
- `scripts/db/010_heartbeat_schema.sql`
- `scripts/db/020_partitioning_auto_daily.sql`
3. 启动服务或执行 `npm run db:apply` 进行初始化。
4. 执行验证项:
- 确认 `heartbeat.heartbeat_events.guid``varchar(32)` 且存在默认值
- 确认存在 `idx_service_mask_first_bit`
- 确认分区新建后存在 `idx_<partition>_service_mask_first_bit`
## 风险评估
- GUID 默认生成依赖 `pgcrypto` 扩展:脚本已包含 `CREATE EXTENSION IF NOT EXISTS pgcrypto;`,但执行账号需要具备安装扩展权限。
- 分区表主键约束限制:无法实现“父表仅 guid 作为主键约束”,因此使用 `(ts_ms, guid)` 的组合主键。
- 表达式索引的表达式匹配:业务查询需要匹配索引表达式(详见 checklist否则无法命中索引。
## 回滚步骤(重建式)
1. 停止服务写入。
2. `DROP SCHEMA heartbeat CASCADE;`(或删除数据库)。
3. 使用回滚版本的 SQL 脚本重新创建(例如回退到 `id bigserial` 版本的脚本)。
4. 重新启动服务并验证写入与查询。