-- CreateIndex
--
-- 【为什么要这条索引】
-- reparse 分批重建源表时,每批取这 3000 个患者的源行(cold-import.service.ts):
--     SELECT id, raw_payload, payload_hash FROM patient_transactions
--     WHERE host_id = $1 AND subject_type IN ('emr','diagnosis') AND patient_id IN (3000 个)
-- 没有 (host_id, subject_type, patient_id) 时 planner 只能走 (patient_id, occurred_at),
-- 把这些患者的**全部** transaction 连 raw_payload 一起捞进堆,再在堆上过滤 host/subject_type。
--
-- 2026-07-27 测试服 EXPLAIN ANALYZE 实测(patient_transactions 12,519,060 行 / 33 GB):
--   Bitmap Heap Scan  actual time=997..10382ms  →  10,385 ms
--   rows=14,578,Rows Removed by Filter: 39,305   ← 读进来 73% 是白读
--   Buffers: shared hit=8,723 read=15,616(约 122MB 磁盘读)
-- 全量 reparse 87 批,单这一句约占 15 分钟。
--
-- ⚠️ 收益如实说:每批总耗时 76–180s,这句占 6–14%,补索引对全程约 4%。
--   reparse 真正的提速手段是 CLI 的 --patients-file(按受影响患者收窄,实测最高 250 倍)。
--   本索引胜在一次性代价、之后每次 reparse / 每个 host 都受益。
--
-- 【体积】(uuid, text, uuid) × 千万行,测试服估 ~600MB、生产(24,074,031 行 / 64GB)估 ~1.2GB。
--   测试服建前 24G 空闲,够;生产上线前请先确认磁盘余量。
--
-- 【CONCURRENTLY 与上线方式】同 20260727070000(sync_log_id 那条):
--   普通 CREATE INDEX 会 ACCESS EXCLUSIVE 锁全表数分钟,摄入与 push 全挂,故用 CONCURRENTLY。
--   当前 Prisma 6.19 可以直接 `migrate deploy` 跑通(20260701060607 里"有事务包裹跑不了"的
--   说法已不成立,2026-07-27 实测)。但**推荐部署前手动先建**:deploy 时 pac-service 要等
--   pac-migrate 退出才启动,几分钟索引构建 = 白等的停机。手动建好后本条 IF NOT EXISTS 空跑:
--     docker exec pac-postgres-1 psql -U pac -d pac -c \
--       'CREATE INDEX CONCURRENTLY IF NOT EXISTS "patient_transactions_host_id_subject_type_patient_id_idx" \
--        ON "patient_transactions"("host_id","subject_type","patient_id");'
CREATE INDEX CONCURRENTLY IF NOT EXISTS "patient_transactions_host_id_subject_type_patient_id_idx" ON "patient_transactions"("host_id", "subject_type", "patient_id");
