本文介绍MaxCompute DECIMAL数据类型的概念、注意事项、使用场景和使用示例。
概述
DECIMAL 是一种用于高精度十进制数值计算的数据类型,广泛应用于金融、科学计算等对精度要求严格的场景。在MaxCompute中,根据项目所采用的数据类型版本不同,DECIMAL 类型的行为存在差异:
关闭DECIMAL 2.0数据类型
DECIMAL 类型采用固定精度格式,默认为
DECIMAL(54,18),precision(最多可以表示多少位的数字)和scale(小数部分位数)值不支持指定。整型部分取值范围:-1036+1~1036-1,小数部分精确到10-18。若使用此数据类型,需设置如下flag:SET odps.sql.decimal.odps2=false;开启DECIMAL 2.0数据类型
默认为
DECIMAL(38,18),用户可以设置其precision(最多可以表示多少位的数字)和scale(小数部分位数)值。根据精度需求分为以下两类:普通 DECIMAL:precision 范围为 [1,38],scale范围为 [0, precision]。若使用此数据类型,需设置如下flag:
SET odps.sql.type.system.odps2=true; SET odps.sql.decimal.odps2=true;精度限制:
若设置
odps.sql.decimal2.extended.scale.enable=false(默认 false):支持 scale 范围为
[0, 18],所有运算结果的小数位将被截断至 18 位。若设置
odps.sql.decimal2.extended.scale.enable=true:支持 scale 范围为
[0, 38]的高精度计算。若设置
odps.sql.decimal256.auto.promotion=true;开启自动类型提升:系统会根据需要将运算结果自动提升为更高精度的 DECIMAL256 类型,以支持更大范围的高精度计算。
DECIMAL256:precision 范围为 [39,76],scale范围为 [0, precision]。若使用此数据类型,需设置如下flag:
SET odps.sql.type.system.odps2=true; SET odps.sql.decimal.odps2=true; SET odps.sql.decimal256.enable=true;
启用odps.sql.decimal256.enable=true时,必须同时将odps.sql.type.system.odps2和odps.sql.decimal.odps2设为true,否则查询将报错。
注意事项
同一个表中不能同时存在新老DECIMAL数据类型。
在DECIMAL 2.0数据类型下,执行
SET odps.sql.hive.compatible=true;命令开启Hive兼容模式,或SET odps.sql.bigquery.compatible=true;命令开启BigQuery兼容模式时,DECIMAL(precision, scale)类型在数据导入(Tunnel Upload)和SQL运算过程中,如果数据的小数位数超过scale的大小,则会四舍五入。如果整数部分超出限制,系统不会报错,但输入数据会变为NULL值。当参数
odps.sql.decimal.tostring.trimzero值为true时去掉小数点后末尾的零,为false时保留小数点后末尾的零。只对表里取数生效,对静态值不生效。默认值为true。
使用场景
数据类型 | 典型配置 | 描述 |
旧版DECIMAL |
| 未开启DECIMAL 2.0数据类型,不支持指定precision/scale,默认为 |
普通DECIMAL |
| 普通DECIMAL类型,precision小于等于38,且在计算过程中,scale被限制不允许超过18。 |
| 普通DECIMAL类型,precision小于等于38,支持 scale 范围为 | |
DECIMAL256 |
| 支持DECIMAL256类型,但在参与运算的DECIMAL的precision小于等于38时,保持原有的行为不变。适合于从普通DECIMAL(scale范围为 |
| 支持DECIMAL256类型,但在参与运算的DECIMAL的precision小于等于38时,保持原有的行为不变。适合于从普通DECIMAL(scale 范围为 | |
| 支持DECIMAL256类型,并且完全发挥了DECIMAL256的能力,适用于没有兼容性要求的全新project。 |
使用示例
关闭DECIMAL 2.0数据类型
示例1:DECIMAL类型默认为DECIMAL(54,18),不支持调整。
-- 关闭Decimal 2.0数据类型
SET odps.sql.decimal.odps2=false;
-- a是DECIMAL类型,取固定的precision/scale (54,18),不支持调整
CREATE OR REPLACE TABLE foo_t(a DECIMAL);
-- 这个create语句会报错,因为在这种模式下不支持用户设置precision/scale
CREATE OR REPLACE TABLE foo_t(a DECIMAL(5,2));
-- 返回报错 FAILED: ODPS-0130071:[1,33] Semantic analysis exception - precision and scale is not currently supported in current mode, 'SET odps.sql.decimal.odps2=true' to enable开启DECIMAL 2.0数据类型
示例1:DECIMAL类型支持指定precision/scale。
-- 开启DECIMAL 2.0数据类型 SET odps.sql.decimal.odps2=true; CREATE OR REPLACE TABLE foo_t(a DECIMAL(4,2));示例2:若DECIMAL类型未指定precision/scale,其默认值取决于 Hive 兼容模式是否开启:关闭时默认为DECIMAL(38,18),开启时默认为DECIMAL(10,0)。
-- 开启DECIMAL 2.0数据类型。,并关闭hive兼容模式 SET odps.sql.decimal.odps2=true; SET odps.sql.hive.compatible=false; CREATE OR REPLACE TABLE foo_t(a DECIMAL); -- 显示a的数类型是DECIMAL(38,18) DESC foo_t; -- 返回结果 +------------------------------------------------------------------------------------+ | Owner: ALIYUN$odps_pd_testcloud_com | | Project: xxxx | | TableComment: | +------------------------------------------------------------------------------------+ | CreateTime: 2026-04-21 13:36:21 | | LastDDLTime: 2026-04-21 13:36:21 | | LastModifiedTime: 2026-04-21 13:36:21 | +------------------------------------------------------------------------------------+ | InternalTable: YES | Size: 0 | +------------------------------------------------------------------------------------+ | Native Columns: | +------------------------------------------------------------------------------------+ | Field | Type | Label | Comment | +------------------------------------------------------------------------------------+ | a | decimal(38,18) | | | +------------------------------------------------------------------------------------+ -- 开启DECIMAL 2.0数据类型,并开启hive兼容模式 SET odps.sql.decimal.odps2=true; SET odps.sql.hive.compatible=true; CREATE OR REPLACE TABLE foo_t(a DECIMAL); -- 显示a的数类型是DECIMAL(10,0) DESC foo_t; -- 返回结果 +------------------------------------------------------------------------------------+ | Owner: ALIYUN$odps_pd_testcloud_com | | Project: ***_project | | TableComment: | +------------------------------------------------------------------------------------+ | CreateTime: 2026-04-21 13:38:04 | | LastDDLTime: 2026-04-21 13:38:04 | | LastModifiedTime: 2026-04-21 13:38:04 | +------------------------------------------------------------------------------------+ | InternalTable: YES | Size: 0 | +------------------------------------------------------------------------------------+ | Native Columns: | +------------------------------------------------------------------------------------+ | Field | Type | Label | Comment | +------------------------------------------------------------------------------------+ | a | decimal(10,0) | | | +------------------------------------------------------------------------------------+示例3:对于普通 DECIMAL,precision 范围为 [1,38],scale范围为 [0, precision]。若需实现scale范围为[0,38]高精度计算,需设置
SET odps.sql.decimal2.extended.scale.enable=true;。SET odps.sql.type.system.odps2=true; SET odps.sql.decimal.odps2=true; -- 开启Decimal 2.0数据类型 SET odps.sql.decimal2.extended.scale.enable=true; -- 开启后,可实现scale范围为[0,38]高精度计算 -- 2个decimal相乘,所得结果的数据类型是decimal(22,19) EXPLAIN SELECT CAST(1bd AS DECIMAL(10,9))*CAST(1bd AS DECIMAL(11,10)); -- 返回结果 job0 is root job In Job job0: root Tasks: M1 In Task M1: VALUES: _c0 : {1} Statistics: Num rows: 1.0, Data size: 16.0 FS: output: Screen schema: _c0 (decimal(22,19)) Statistics: Num rows: 1.0, Data size: 16.0 -- 将flag设置为false,输出类型的scale被截断到18,变成了decimal(22,18) SET odps.sql.decimal2.extended.scale.enable=false; -- 关闭后,scale范围为 [0,18] EXPLAIN SELECT CAST(1bd AS DECIMAL(10,9))*CAST(1bd AS DECIMAL(11,10)); -- 返回结果 job0 is root job In Job job0: root Tasks: M1 In Task M1: VALUES: _c0 : {1} Statistics: Num rows: 1.0, Data size: 16.0 FS: output: Screen schema: _c0 (decimal(22,18)) Statistics: Num rows: 1.0, Data size: 16.0示例4:对于DECIMAL256,precision 范围为 [39,76]。scale范围为 [0, precision]。
SET odps.sql.type.system.odps2=true; SET odps.sql.decimal.odps2=true; SET odps.sql.decimal256.enable=true; CREATE OR REPLACE TABLE foo_t(a decimal(60,10)); EXPLAIN SELECT * FROM foo_t; -- 返回结果 job0 is root job In Job job0: root Tasks: M1 In Task M1: Data source: ***_project.foo_t TS: muze_project.foo_t Statistics: Num rows: 1.0, Data size: 16.0 FS: output: Screen schema: a (decimal(60,10)) Statistics: Num rows: 1.0, Data size: 16.0示例5:两个普通DECIMAL进行运算,默认情况下,所得的结果是普通DECIMAL类型,若超出范围会对数据进行截断。
SET odps.sql.type.system.odps2=true; SET odps.sql.decimal.odps2=true; -- 结果类型为 decimal(38,5),因超出普通 DECIMAL 范围而被截断 EXPLAIN SELECT CAST(1bd AS DECIMAL(30,5)) * CAST(1bd AS DECIMAL(30,0)); -- 返回结果 job0 is root job In Job job0: root Tasks: M1 In Task M1: VALUES: _c0 : {1} Statistics: Num rows: 1.0, Data size: 16.0 FS: output: Screen schema: _c0 (decimal(38,5)) Statistics: Num rows: 1.0, Data size: 16.0而当启用
DECIMAL256并设置SET odps.sql.decimal256.auto.promotion=true;开启自动类型提升后,系统会将运算结果自动提升至DECIMAL256支持的更高精度类型,从而避免截断,保留完整精度。SET odps.sql.type.system.odps2=true; SET odps.sql.decimal.odps2=true; SET odps.sql.decimal256.enable=true; SET odps.sql.decimal256.auto.promotion=true; -- 结果类型是decimal(61,5),两个普通decimal相乘的结果被promote到decimal256的范围中 EXPLAIN SELECT CAST(1bd AS DECIMAL(30,5)) * CAST(1bd AS DECIMAL(30,0)); -- 返回结果 job0 is root job In Job job0: root Tasks: M1 In Task M1: VALUES: _c0 : {1} Statistics: Num rows: 1.0, Data size: 16.0 FS: output: Screen schema: _c0 (decimal(61,5)) Statistics: Num rows: 1.0, Data size: 16.0