Commit 8470c2f5 by luoqi

merge: main → test(反向合)

parents a267668f 6dc62917
Pipeline #3648 failed in 0 seconds
......@@ -72,6 +72,92 @@ received_at 08-25 12:39 ← PAC 47 小时后才看到
> 🔴 **这个测量的方向是单边的**:它能证明「48h 绰绰有余」,**不能**证明「48h 不够」。
> 而现在数据显示边界被顶到了,连"绰绰有余"都谈不上。别拿单边结论去支撑双边决策。
## 4b. 证据链:确认是 DW 侧没有,不是我们没去问
**决定性判据**(只用 PAC 自己的数据,可复现):一行出现在第 N 轮,而它的 `updated_date`
在第 N−1、N−2… 轮的窗口里**就已经被覆盖** → 证明 DW 当时确实没有这行。
以那条 47.4 小时的退费为例(`updated_date=08-23 13:13`,`received_at=08-25 12:39`):
```
08-23 14:15 sync fetched=231,515 窗口下界 08-21 14:15 ✅ 覆盖 → 没拉到
08-23 16:15 sync fetched=235,101 ✅ → 没拉到
…(共 17 轮增量,全部 success)…
08-24 20:09 FULL fetched=4,914,444 ← 全表重读,不看游标 → 仍没拉到
08-25 02:22 FULL fetched=4,255,188 ← 再次全表重读 → 仍没拉到
08-25 12:15 sync fetched=213,108 窗口下界 08-23 12:15 → **拉到了**
```
**19 次查询(含 2 次把 DW 整个重读一遍)都看不见,第 20 次看见了。**
最后那轮的窗口下界是 08-23 12:15,记录是 13:13 —— **只剩 58 分钟余量**,再晚一轮就永久丢。
### 游标的真实语义(容易读错)
```ts
// cold-import.service.ts
// ⭐ cursor_after = run_start ISO(关键!不是 max(updated_date))
const ignoreCursor = options.incremental === false; // full: 忽略游标,全表重读
```
游标推进用的是**墙钟(本轮启动时刻)**,不是数据里的 `max(updated_date)`
每轮查询下界 = `上轮 run_start − 48h`
⚠️ 原注释的理由「run_start 之后 DW 任何写入,下次增量 `WHERE > run_start` 都能捞回」
**有漏洞**:过滤的是 `updated_date`,不是"DW 何时写的"。若 DW 写入时该行
`updated_date` 已早于 `(游标 − 48h)`,下次也捞不回来 —— 这正是漏拉的机制。
## 4c. 「DW 承诺 2 小时更新」与实测的差距
若承诺成立,滞后应封顶 ~4h(2h 刷新 + 2h 等下一轮)。实测(7 天 / 28.2 万条):
| 表 | 条数 | >6h | >12h | >24h |
|---|---|---|---|---|
| **refund** | 150 | **18.7%** | **18.7%** | **27** |
| **recommendation** | 2,631 | **18.9%** | 4.1% | 0 |
| image | 48,348 | 7.8% | 1.3% | 0 |
| diagnosis | 32,763 | 7.5% | 2.1% | 0 |
| treatment | 48,884 | 6.9% | 2.1% | **4** |
| emr | 25,362 | 6.2% | 1.7% | 0 |
| encounter | 30,490 | 2.5% | 1.8% | 0 |
| payment | 8,548 | 2.5% | 0.2% | 0 |
| appointment | 84,380 | 2.3% | 1.0% | 0 |
**中位数守住了(p50 2.39h),尾巴没守住。****分表差异极大**
(appointment 2.3% vs recommendation 18.9% vs refund 18.7%)——
指向 DW 内部不同表走不同的 ETL 链路/调度,不是整体延迟。
`recommendation` 是召回的第二信号源,18.9% 超 6 小时,直接影响召回时效。
## 4d. 🔴 数据时效与丢失边界是**同一个数**
```
PAC 能拿到的数据:最坏 T+2(47.43h 实测)
丢失边界 :48h
```
不是"DW 最慢两天",而是**比 T+2 更晚的根本进不来**。所以:
- **能看见的迟到**:0~48 小时
- **看不见的迟到**:>48 小时 —— 从每轮窗口掉出去,**永远不会知道它存在过**
### 漏掉的数据不会自动修复
`full:` 全量补摄忽略游标、全表重读,机制上能捞回所有迟到数据。
**但生产的全量补摄是人工临时跑的,没有定时任务**:
```
08-21 ×4 08-22 ×2 08-24~08-26 ×5(批量补摄期间)
最近一次:08-26 07:08
```
**08-26 之后漏掉的至今还漏着。**
### 两个未采纳的兜底(记录备查)
| 方案 | 作用 | 代价 |
|---|---|---|
| **定期全量补摄**(如每周一次凌晨) | 把"可能永久漏"变成"最多漏一周" | 单次拉取 300~500 万行,需挑窗口 |
| **跟 DW 对账**:要某历史时段的行数与 PAC 库比对 | **唯一能回答"到底漏了多少"的办法**,其余都是推断 | 只读,需 DW 配合提供计数 |
## 5. 根治办法(不在我们这边):请 DW 提供入仓时间列
**DW 当前一个入仓时间字段都没有。** 十张表的时间列只有 `created_date` / `updated_date`,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment