3. 多源数据挑战
在真实行情系统中,同一只股票的价格往往同时来自交易所直连、券商柜台、第三方数据商、网页抓取接口等多个通道。多源接入的初衷是提升覆盖率与容错能力,但随之而来的是一组高度耦合的数据治理难题:不同源对同一事实的描述方式不一致,导致“看起来都是行情,却无法直接合并”。本节聚焦四类核心挑战——数据源差异、时间戳偏差、字段映射、重复与冲突,并给出可落地的识别与处理思路。
一、核心原理:多源差异的本质是“语义与时钟不同步”
多源数据之所以难以去重,根本原因不在数据本身,而在于三个层面的不同步:语义层(字段含义、单位、精度不同)、时间层(采集时刻、事件时刻、入库时刻不同)、标识层(同一标的在不同源中的代码、名称、市场后缀不同)。去重与主键设计,本质上是在这三层之间建立可对齐的“锚点”。
例如,A源返回 last_price 单位为元、保留两位小数;B源返回 price 单位为分、整数存储。若不做单位归一,同一笔成交会被判为两条不同记录。再如,A源时间戳为交易所撮合时间,B源为本地接收时间,两者相差数十毫秒,若直接按时间戳去重,会误删真实的不同快照。
二、方法流程:从字段映射到冲突裁决
处理多源数据,建议按“先对齐、再判重、后裁决”的顺序推进,避免在未归一的情况下直接去重。
- 字段映射:建立源字段到标准字段的映射表,明确单位换算与精度规则。例如
price分转元需除以100,vol手转股需乘以100。 - 时间对齐:区分事件时间与采集时间,统一到同一时区与精度(如毫秒)。对采集时间偏差较大的源,优先使用事件时间作为主键组成部分。
- 标识归一:将各源代码统一为标准 symbol,如
600519.SH,并保留原始代码作为溯源字段。 - 判重:以“标准symbol + 事件时间 + 业务类型”为候选主键,识别同一事实的多条记录。
- 冲突裁决:当同一主键下字段值不一致时,按源优先级、时间新鲜度或多数投票规则选择保留值。
关键原则:去重不是简单删除,而是“识别同一事实并保留最优表达”。主键设计要能同时支撑判重与溯源,因此建议保留 source 与 ingest_time 作为辅助字段。
三、案例场景:同一笔成交的多源记录
假设某时刻贵州茅台发生一笔成交,三个源返回如下:
| 源 | 代码 | 价格 | 时间戳 | 类型 |
|---|---|---|---|---|
| A(交易所直连) | 600519.SH | 1680.00 元 | 10:00:00.120 | 事件时间 |
| B(第三方) | SH600519 | 168000 分 | 10:00:00.185 | 采集时间 |
| C(网页抓取) | 600519 | 1680.0 元 | 10:00:01.000 | 采集时间 |
若直接按原始字段去重,三条记录代码、单位、时间均不同,会被误判为三笔独立成交。正确做法是:先归一代码为 600519.SH,价格统一为元,时间统一到事件时间并允许±200ms容差,再以 symbol + event_time_bucket + trade_type 判重。此时A与B可合并为同一事实,C因时间偏差较大需结合业务判断是否保留为独立快照。
-- 归一与判重示例
SELECT
standard_symbol,
DATE_TRUNC('second', event_time) AS time_bucket,
trade_type,
COUNT(*) AS source_count,
MAX_BY(price, source_priority) AS final_price
FROM normalized_market_data
GROUP BY standard_symbol, time_bucket, trade_type;
四、误区与复盘
常见误区一:用采集时间做主键。采集时间受网络与调度影响,同一事件在不同源可能相差数百毫秒甚至数秒,直接做主键会导致大量伪重复。
常见误区二:忽略单位与精度。价格分与元、成交量手与股未归一,去重结果必然失真。
常见误区三:冲突时简单取最新。最新采集的记录未必最准确,应结合源优先级与业务规则综合裁决。
复盘时建议建立“多源差异清单”,逐项记录每个源的字段含义、时间语义、代码格式与已知偏差,并定期用抽样比对验证映射规则是否仍然有效。只有把差异显性化、规则化,去重与主键设计才能从“救火”走向“可运营”。