首页/数据/数仓建模速查/DECIMAL 精度选择规范
分层与规范64 条

DECIMAL 精度选择规范

金额用 DECIMAL(18,2)、汇率与比率用 DECIMAL(10,4) 或更高、单价可用 DECIMAL(18,4);避免用 FLOAT/DOUBLE 存金额造成舍入误差。

数仓建模速查数据更新于 2026-10-13

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);一旦超出范围,写入会溢出或直接失败。
金额字段参与比较和取模时要留意小数位:两位小数的字段做除法后再四舍五入,结果可能与业务系统先折算后取整的顺序不同,涉及分账与结算的场景要在口径里写明运算顺序。

易错点

  • 用 DOUBLE 存金额:汇总求和出现尾差,财务对账无法解释
  • 各层金额精度不一致(一层两位、一层四位):join 时隐式转换,出现微小差异且难定位
  • 精度不足直接承接口径较大的金额:超出取值范围后溢出或被截断
  • 只改上游字段类型不回刷历史:新旧分区精度不同,汇总结果不一致

数据来源与参考

  • MySQL 8.0 Reference Manual: Numeric Types
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌