DECIMAL 精度选择规范
金额类字段统一用 DECIMAL(18,2),比率与汇率用 DECIMAL(10,4) 或更高,单价可以用 DECIMAL(18,4);禁止用 FLOAT 或 DOUBLE 存金额。浮点是二进制近似表示,多次汇总后会出现 0.01 级别的尾差,财务对账时这笔差额无法解释,只能整段重算。
基本信息
| 金额 | DECIMAL(18,2) |
|---|---|
| 比率与汇率 | DECIMAL(10,4) 起 |
| 单价 | DECIMAL(18,4) |
| 禁止 | FLOAT / DOUBLE 存金额 |
| 一致性 | 同一指标在各层精度保持一致 |
典型使用场景
- 新建金额字段按用途选精度:支付金额两位小数,单价四位小数
- 跨层传递:ODS 用字符串承接,DWD 起统一为 DECIMAL(18,2),避免逐层漂移
- 汇总核对:与业务系统总额比对,差一分钱也要定位到原因
- 汇率换算:明确汇率精度与换算时机(入仓时换算还是查询时换算)
- 类型改造:把历史表的浮点金额改为 DECIMAL 时按分区回刷并校验汇总一致性
精度定义
精度定义
CREATE TABLE ads_trade_fin_day (
pay_amt DECIMAL(18,2) COMMENT '支付金额(元)',
refund_amt DECIMAL(18,2) COMMENT '退款金额(元)',
refund_rate DECIMAL(10,4) COMMENT '退款率(小数,四位)',
unit_price DECIMAL(18,4) COMMENT '单价(元,四位)',
fx_rate DECIMAL(10,4) COMMENT '汇率(对 CNY)'
) PARTITIONED BY (dt STRING);精度选择参考
| 用途 | 建议类型 | 说明 |
|---|---|---|
| 金额 | DECIMAL(18,2) | 到分位,整数部分足以承载汇总 |
| 比率 | DECIMAL(10,4) | 保留四位小数 |
| 单价 | DECIMAL(18,4) | 单价小数位通常多于金额 |
| 禁止项 | FLOAT / DOUBLE | 二进制近似,汇总出现尾差 |
用浮点存金额时汇总会出现 0.01 级别漂移,而且不同引擎的取舍方向可能不同,跨系统对账时差额来源几乎无法解释。
把 DOUBLE 改成 DECIMAL 需要按分区回刷历史并同步下游字段类型;只改上游会让 join 与比较产生隐式转换,结果和性能都会受影响。
整数部分位数按业务上限留足余量:金额用 DECIMAL(18,2) 通常能覆盖到千亿级汇总,不必为了省空间压缩到 (10,2);一旦超出范围,写入会溢出或直接失败。
金额字段参与比较和取模时要留意小数位:两位小数的字段做除法后再四舍五入,结果可能与业务系统先折算后取整的顺序不同,涉及分账与结算的场景要在口径里写明运算顺序。