perf(reparse): patient_transactions 补 (host_id, subject_type, patient_id) 复合索引
reparse 分批取源行那句:
SELECT id, raw_payload, payload_hash FROM patient_transactions
WHERE host_id = $1 AND subject_type IN ('emr','diagnosis') AND patient_id IN (3000 个)
没这条索引时 planner 只能走 (patient_id, occurred_at),把这 3000 个患者的**全部**
transaction 连 raw_payload 一起捞进堆,再在堆上过滤 host_id / subject_type。
2026-07-27 测试服 EXPLAIN ANALYZE 实测(12,519,060 行 / 33GB):
Bitmap Heap Scan 10,385 ms
rows=14,578,Rows Removed by Filter: 39,305 ← 读进来 73% 是白读
Buffers: read=15,616(约 122MB 磁盘读)
全量 87 批,单这一句约占 15 分钟。本地建索引后 planner 已改走
Index Scan using patient_transactions_host_id_subject_type_patient_id_idx。
⚠ ️ 收益如实说:每批总耗时 76–180s,这句只占 6–14%,对全程约 4%,**不是提速主手段**。
reparse 真正的杠杆是上一个提交的 --patients-file(按受影响患者收窄,实测最高 250 倍)。
本索引胜在一次性代价、之后每次 reparse / 每个 host 都受益。
体积:(uuid,text,uuid) × 千万行,测试服估 ~600MB、生产(2407 万行 / 64GB)估 ~1.2GB。
测试服建前 24G 空闲够用;生产上线前需先确认磁盘余量。
上线方式同 20260727070000:CONCURRENTLY(不锁写),推荐部署前手动先建 ——
deploy 时 pac-service 要等 pac-migrate 退出才启动,几分钟索引构建 = 白等的停机;
手动建好后本迁移 IF NOT EXISTS 空跑。
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Showing