账户域的三件套
账户域的经典组合是:交易流水事实表(一笔交易一行,借方与贷方金额分开存放)、日终余额快照(账户乘以日,记录期末余额)、账户维度。流水回答发生了什么,快照回答某时点余额是多少,两者必须能勾稽:当日流水净额加上期初余额等于期末余额。
基本信息
| 流水粒度 | 一笔交易一行,交易流水号唯一 |
|---|---|
| 快照粒度 | 账户乘以日,一天一个账户一行 |
| 账户维度 | 代理键、客户号、开户机构、账户类型 |
| 金额单位 | 最小货币单位的整数(分),避免浮点误差 |
| 勾稽校验 | 期初余额加当日净额等于期末余额 |
典型使用场景
- 账户流水查询:按客户、账户与时间范围列出借贷明细
- 日终余额报表:直接从快照取数,不必每天重算全量流水
- 资金监控:识别大额、高频与异地异常交易
- 计息与收费:期初余额与当日发生额是利息和手续费的计算输入
- 审计与对账:流水与快照逐日勾稽,差异可定位到具体账户与日期
交易流水表与逐日勾稽
交易流水表与逐日勾稽
-- 借贷双向金额:dr 借方、cr 贷方,单位统一为分
CREATE TABLE fact_acct_txn (
txn_id string COMMENT '交易流水号',
acct_sk bigint COMMENT '账户代理键',
txn_type string COMMENT '交易类型编码',
dr_amt bigint COMMENT '借方金额,单位分',
cr_amt bigint COMMENT '贷方金额,单位分',
txn_ts timestamp COMMENT '记账时间'
) PARTITIONED BY (dt string) STORED AS ORC;
-- 逐日勾稽:期初加当日净额必须等于期末
SELECT count(1) AS bad_cnt
FROM fact_acct_balance_daily b
LEFT JOIN (SELECT acct_sk, sum(dr_amt) - sum(cr_amt) AS net
FROM fact_acct_txn WHERE dt = '2026-10-12' GROUP BY acct_sk) t
ON b.acct_sk = t.acct_sk
WHERE b.dt = '2026-10-12'
AND b.open_bal + coalesce(t.net, 0) <> b.close_bal;流水与快照的分工
| 对比项 | 交易流水 | 日终余额快照 |
|---|---|---|
| 粒度 | 交易笔级 | 账户乘以日 |
| 主键 | 交易流水号 | 账户加日期 |
| 回答的问题 | 发生了什么 | 某时点有多少 |
| 数据量 | 大,需按时间与账户归档 | 中等,可长期保留 |
| 在勾稽中的角色 | 当日净额来源 | 提供期初与期末 |
借贷方向与正负号只能有一套约定:业务侧统一存借、贷两个非负金额,报表再派生符号,混用两套约定会在净额汇总时出现方向性错误。
金额一律用整数分存储:浮点数在小数位累积误差后勾稽会恒不成立,且这类错误难以复现,排查成本远高于改用整数。