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

2.7 KiB
Raw Blame History

service_mask 索引性能对比报告

结论摘要(如何判定“提升”)

  • service_mask 位运算过滤场景中,新增 idx_service_mask_first_bit 后,查询计划应从 Seq Scan 转为 Index Scan/Bitmap Index Scan(并触发分区裁剪时,仅扫描命中的分区)。
  • 若过滤选择性较高(例如仅小比例满足 “&1=1”通常能显著降低 IO 与响应时间。

索引脚本

  • 结构与索引创建包含在:
    • scripts/db/010_heartbeat_schema.sql
    • scripts/db/020_partitioning_auto_daily.sql
  • 关键语句:
    • CREATE INDEX idx_service_mask_first_bit ON heartbeat.heartbeat_events ((service_mask & 1));

测试方法(可复现)

1) 数据准备

建议在测试库中写入至少 100 万行,保证计划稳定:

SELECT heartbeat.ensure_partitions(current_date, current_date + 1);

INSERT INTO heartbeat.heartbeat_events (
  ts_ms, hotel_id, room_id, device_id, ip,
  power_state, guest_type, cardless_state, service_mask,
  pms_state, carbon_state, device_count, comm_seq, extra
)
SELECT
  (extract(epoch from now()) * 1000)::bigint + (g % 86400000),
  (g % 1000)::int2,
  ('R' || (g % 500))::varchar(50),
  ('D' || (g % 20000))::varchar(64),
  '127.0.0.1:1',
  1, 0, 0,
  (g % 1024)::bigint,
  0, 0, 1, (g % 100000)::int4,
  jsonb_build_object('src','bench')
FROM generate_series(1, 1000000) g;

ANALYZE heartbeat.heartbeat_events;

2) 对比维度

  • 响应时间:EXPLAIN (ANALYZE, BUFFERS)Execution Time
  • QPS用同一 SQL 连续执行 N 次(例如 1000 次)并统计平均耗时(由压测端计算)
  • 查询形态:
    • 形态 A位运算表达式命中表达式索引
      • WHERE (service_mask & 1) = 1

修改前/后对比(需要在目标环境产出)

说明:不同硬件/数据分布/缓存命中会导致数值差异。以下对比表格请在你的环境执行本报告“测试方法”并填入实际输出。

A. 修改前(无 idx_service_mask_first_bit

  • 查询计划期望Seq Scan 或 Bitmap Heap Scan + BRIN
EXPLAIN (ANALYZE, BUFFERS)
SELECT count(*)
FROM heartbeat.heartbeat_events
WHERE (service_mask & 1) = 1;
  • 结果记录:
    • QPS1000 次____
    • P50 响应时间ms____
    • P95 响应时间ms____

B. 修改后(有 idx_service_mask_first_bit

EXPLAIN (ANALYZE, BUFFERS)
SELECT count(*)
FROM heartbeat.heartbeat_events
WHERE (service_mask & 1) = 1;
  • 结果记录:
    • 位运算表达式命中索引期望Index/Bitmap Index Scan
      • QPS1000 次____
      • P50ms____
      • P95ms____

结论与建议

  • 业务使用 WHERE (service_mask & 1) = 1 可直接命中 idx_service_mask_first_bit