-- CreateIndex
--
-- 【为什么要这条索引】
-- 每次摄入收尾都要按 sync_log_id 反查本轮 touched 患者
-- (cold-import.service.ts `touchedRows`,push / cold-import / 增量共用这一条路径):
--     SELECT id, patient_id, tenant_id FROM patient_transactions
--     WHERE sync_log_id = $1 AND patient_id IS NOT NULL
-- 外键约束**不会**自动建索引,所以这句一直在全表扫。
--
-- 2026-07-27 测试服实测(FRIDAY 对接增量 push 报 SocketTimeoutException 时定位到):
--   推 2 行患者主档 → 单次请求 74s,74s 全耗在上面这条 SQL(逐 6s 采 pg_stat_activity,
--   同一条查询年龄从 6s 一路涨到 74s);EXPLAIN:
--     Parallel Seq Scan on patient_transactions  (cost=0.00..2150645.78 rows=1579)
--   patient_transactions:测试服 12,519,060 行 / 33 GB;生产 24,074,031 行 / 64 GB。
--   建索引后本地实测 plan 变 Index Scan(cost=0.29..4.31)。
--   这条随摄入量增长只会更糟 —— 属结构性缺失,不是调优。
--
-- 【CONCURRENTLY 与上线方式】
-- 普通 CREATE INDEX 会 ACCESS EXCLUSIVE 锁全表,33/64GB 上要锁几分钟,期间摄入与 push 全挂,
-- 故用 CONCURRENTLY(不锁写)。
--
-- ⚠️ 关于「Prisma migrate 有事务包裹所以跑不了 CONCURRENTLY」——
--    本条实测能随 migrate deploy 跑通,但**别把它总结成「Prisma 新版已经没事务包裹了」**
--    (本文件原来就是这么写的,错的归因,2026-07-28 已订正)。
--    真正的分界线是**本文件里的语句条数**:Prisma 把整份 migration.sql 用一次 simple query
--    发给 Postgres,而 Postgres 只对「一个查询串里多条语句」隐式开事务块。
--    本文件只有 1 条语句 → 没有隐式事务 → CONCURRENTLY 跑得通;
--    多条语句的迁移里写 CONCURRENTLY 必挂 25001,还会把 _prisma_migrations 堵死(P3018)。
--    2026-07-28 的 20260728020000 就是这么炸的,那份文件头有完整复盘。
--
-- 但**推荐仍手动先建**,理由与事务无关,是停机时间:
--   deploy 时 pac-service 通过 depends_on 等 pac-migrate 退出才启动,而 33/64GB 建索引要几分钟
--   → 白等一段服务不可用。先手动建好(业务照常),deploy 时本条 IF NOT EXISTS 直接空跑:
--     docker exec pac-postgres-1 psql -U pac -d pac -c \
--       'CREATE INDEX CONCURRENTLY IF NOT EXISTS "patient_transactions_sync_log_id_idx" \
--        ON "patient_transactions"("sync_log_id");'
CREATE INDEX CONCURRENTLY IF NOT EXISTS "patient_transactions_sync_log_id_idx" ON "patient_transactions"("sync_log_id");
