Files
Web_BLS_Heartbeat_Server/docs/db-guid-pk-and-service-mask-index-plan.md

41 lines
2.2 KiB
Markdown
Raw Permalink Normal View History

# 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. 重新启动服务并验证写入与查询。