Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
P
pac
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
ai-tools
pac
Commits
8470c2f5
Commit
8470c2f5
authored
Aug 31, 2026
by
luoqi
Browse files
Options
Browse Files
Download
Plain Diff
merge: main → test(反向合)
parents
a267668f
6dc62917
Pipeline
#3648
failed in 0 seconds
Changes
1
Pipelines
1
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
86 additions
and
0 deletions
+86
-0
docs/design/ingest-lookback-analysis.md
+86
-0
No files found.
docs/design/ingest-lookback-analysis.md
View file @
8470c2f5
...
@@ -72,6 +72,92 @@ received_at 08-25 12:39 ← PAC 47 小时后才看到
...
@@ -72,6 +72,92 @@ received_at 08-25 12:39 ← PAC 47 小时后才看到
> 🔴 **这个测量的方向是单边的**:它能证明「48h 绰绰有余」,**不能**证明「48h 不够」。
> 🔴 **这个测量的方向是单边的**:它能证明「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 提供入仓时间列
## 5. 根治办法(不在我们这边):请 DW 提供入仓时间列
**DW 当前一个入仓时间字段都没有。**
十张表的时间列只有
`created_date`
/
`updated_date`
,
**DW 当前一个入仓时间字段都没有。**
十张表的时间列只有
`created_date`
/
`updated_date`
,
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment