4. 临床数据采集与接入工程

临床数据采集与接入是专题数据集市的第一道工程关口。它要解决的核心问题不是“能不能把数据搬过来”,而是“搬过来的数据是否完整、及时、可追溯、可重放”。在真实医院环境中,数据源往往同时包含 HIS 业务库、LIS 检验系统、PACS 影像报告、电子病历文书、护理记录、设备监护流以及第三方上传文件。不同来源的更新频率、数据量级、接口能力和合规约束差异极大,因此接入层必须按数据特征选择批量抽取、增量捕获、接口对接、文件导入或实时流接入中的一种或多种组合,而不是用单一通道硬套所有场景。

五类接入通道的适用边界

批量抽取适合历史数据初始化、T+1 全量对账和低频维表同步。典型做法是通过 JDBC 或数据库导出工具,在业务低峰期按分区或按时间窗口拉取,例如每晚 01:00 抽取前一日出院病案首页。它的优点是实现简单、对源库压力可控;缺点是时效性差,且必须解决“抽取过程中源数据仍在变化”导致的一致性缺口。

增量捕获适合高价值业务表的准实时同步。常见实现包括基于时间戳/自增序列的轮询增量、基于数据库日志的 CDC(如 MySQL binlog、Oracle LogMiner、PostgreSQL 逻辑复制)。时间戳增量实现成本低,但要求源表有可靠且单调的更新时间字段,且无法捕获物理删除;日志级 CDC 能捕获插入、更新、删除,但需要额外权限、日志保留窗口和位点管理。工程上必须记录“上次成功位点”,并支持断点续传与重复消费幂等。

接口对接适合跨机构、跨系统或受控访问场景,例如通过 HL7 v2 消息、FHIR RESTful API、WebService 获取患者、就诊、检验结果。接口对接的关键不在调用本身,而在于约定分页、限流、重试、鉴权和错误码语义。例如 FHIR 接口常用 _count 与 _offset 分页,遇到 429 应退避重试,遇到 401 应刷新令牌而不是无限重试。

文件导入适合批量补录、外部机构交付和无法直连的系统。CSV、Excel、XML、JSON、DICOM 文件都可能出现。文件导入必须做“落地—校验—入库”三段式处理:先原样归档,再解析校验,最后写入贴源层,避免解析失败后原始文件丢失。

实时流接入适合监护设备、急诊看板、手术麻醉等对延迟敏感的场景。通常通过 Kafka、MQTT 或 WebSocket 接收消息,按患者标识和事件时间做窗口聚合。实时流接入必须处理乱序、重复和迟到数据,常用事件时间加水印机制,并保留原始消息以便回放。

临床数据接入五通道与质量控制链路 数据源 HIS 业务库 LIS / PACS EMR 文书 监护设备流 外部交付文件 第三方 API 历史归档库 接入通道 批量抽取 JDBC / 分区拉取 增量捕获 时间戳 / CDC 日志 接口对接 HL7 / FHIR / WS 文件导入 CSV / XML / DICOM 实时流接入 Kafka / MQTT 质量控制 完整性校验 主键去重 时间戳一致性 编码映射校验 空值率监控 延迟与积压告警 对账与重放 贴源层 ODS 原始落地 保留源字段 批次/位点标记 可追溯血缘 支持重放 → 数据集市 核心原则:先落地后加工 · 位点可续传 · 批次可对账 · 异常可重放 · 血缘可追溯

增量捕获的位点管理与幂等设计

增量捕获最容易出问题的不是“怎么读日志”,而是“位点怎么存、失败怎么恢复”。以 MySQL binlog 为例,接入任务需要维护 binlog_file 与 binlog_position 两个位点,并在目标贴源层写入成功后,才把位点提交到元数据库。若先提交位点再写目标,一旦写入失败就会丢数据;若先写目标再提交位点,重复消费时可能产生重复记录,因此目标表必须按业务主键做幂等写入,例如使用 INSERT ... ON DUPLICATE KEY UPDATE 或先删后插的批次覆盖策略。

对于基于时间戳的轮询增量,需要额外处理“同一时间戳多条记录”和“源库时间回拨”两个边界。常见做法是采用 (update_time, id) 组合游标,查询条件写成 update_time > :last_time OR (update_time = :last_time AND id > :last_id),并按 update_time, id 排序分页。这样即使同一秒内有多条更新,也不会漏读或重复。

接口对接与文件导入的工程细节

接口对接要区分“拉”和“推”。拉取型接口需要处理分页、限流和增量水位;推送型接口需要提供接收端点、验签、去重和落库确认。以 FHIR 患者查询为例,一次典型请求可写为:

GET /fhir/Patient?_lastUpdated=gt2024-06-01T00:00:00Z&_count=100&_offset=0
Headers:
  Authorization: Bearer <token>
  Accept: application/fhir+json

返回结果中若 total 大于当前页数量,应继续翻页直到取完;若返回 429,则按指数退避等待 1s、2s、4s 后重试,并记录重试次数。所有接口响应都应保留原始报文摘要和业务主键,便于后续对账。

文件导入的关键是“先归档、再解析、后入库”。例如一批外部检验 CSV 文件到达后,先按 来源系统/日期/文件名 归档到原始区,再逐行解析。解析时至少校验:文件行数是否与清单一致、必填列是否为空、患者标识能否映射、检验项目编码是否在字典表中。若某行校验失败,不应整批丢弃,而应写入错误表并标记行号,允许修正后重跑该批次。

实时流接入的乱序与迟到处理

监护设备流通常带有设备时间戳,但网络传输会导致到达顺序与事件顺序不一致。工程上应以事件时间作为窗口划分依据,并设置水印容忍迟到。例如设定水印延迟为 30 秒,则窗口 [10:00:00, 10:01:00) 在收到 10:01:30 之后的水印时才触发计算。对于超过水印的迟到数据,可写入侧输出流单独处理,而不是直接丢弃。同时,每条消息应携带 device_id + measure_time + metric_code 作为去重键,防止网络重传造成重复计数。

质量控制与对账闭环

接入质量不能只看“任务是否跑成功”,而要看数据是否可信。建议在每个通道落地后执行四类检查:第一,完整性检查,比对源端记录数与目标端记录数,偏差超过阈值即告警;第二,主键唯一性检查,确认贴源层无重复主键;第三,时间戳合理性检查,识别未来时间、过早时间和空时间;第四,编码映射检查,统计未匹配字典的编码占比。对于批量抽取,还应按批次生成对账文件,记录批次号、抽取起止时间、源端行数、目标端行数、失败行数和重试次数,作为后续审计和问题定位的依据。

接入层设计的一个实用原则是:任何一条数据都必须能回答“从哪来、什么时候来、经过哪个通道、落在哪张表、是否通过校验、失败后如何重跑”。这六个问题构成了临床数据接入可运维性的最小闭环。

综合来看,批量抽取、增量捕获、接口对接、文件导入和实时流接入并不是互斥选项,而是按数据时效、数据量、源系统能力和合规要求组合使用的工具箱。工程实现的重点在于:为每条通道定义清晰的位点或批次标识,为每次写入设计幂等策略,为每类异常保留可重放的原始数据,并为每个批次建立可对账的质量指标。只有这样,贴源层才能真正成为专题数据集市可信、可追溯、可恢复的数据底座。