MaxCompute2.0较1.0版本执行更严格的语法检测,在MaxCompute1.0中可以正常执行的不严谨语法在MaxCompute2.0中则会报错。本文为您介绍具体报错信息及解决方案。
ODPS-0130071 divide nan or overflow
- Case 1。
- 问题描述。
- MaxCompute1.0不会进行除法常量折叠,在MaxCompute1.0中如下语句对应的物理执行计划如下:
EXPLAIN SELECT IF(FALSE, 0/0, 1.0) FROM dual; In Task M1_Stg1: Data source: meta_dev.dual TS: alias: dual SEL: If(False, Divide(UDFToDouble(0), UDFToDouble(0)), 1.0) FS: output: None
可以看出IF和Divide函数仍然保留,运行时因为IF第一个参数为FALSE,第二个参数Divide表达式不需要求值,所以不会出现除零异常。
- MaxCompute2.0支持除法常量折叠,所以在MaxCompute2.0中如下语句会报错。
SELECT IF(FALSE, 0/0, 1.0) FROM dual; --报错 FAILED: ODPS-0130071:[1,19] Semantic analysis exception - encounter runtime exception while evaluating function /, detailed message: DIVIDE func result NaN, two params are 0.000000 and 0.000000
- 除了上述的问题,还可能遇到Overflow错误,如下所示。
SELECT IF(FALSE, 1/0, 1.0) FROM dual; --报错 FAILED: ODPS-0130071:[1,19] Semantic analysis exception - encounter runtime exception while evaluating function /, detailed message: DIVIDE func result overflow, two params are 1.000000 and 0.000000
- MaxCompute1.0不会进行除法常量折叠,在MaxCompute1.0中如下语句对应的物理执行计划如下:
- 解决方案。
建议去掉
/0
用法,换成合法常量。
- 问题描述。
- Case 2。
- 问题描述。
CASE WHEN常量折叠也有类似问题,例如
CASE WHEN TRUE THEN 0 ELSE 0/0
语句,在MaxCompute2.0中常量折叠时所有子表达式都会求值,导致除0错误。CASE WHEN可能涉及如下更复杂的优化场景。
优化器会将除法下推到子查询中,转换成类似如下命令,运行后报错。SELECT CASE WHEN key = 0 THEN 0 ELSE 1/key END FROM ( SELECT 0 AS key FROM src UNION ALL SELECT key FROM src) r;
其中SELECT c1 END FROM ( SELECT CASE WHEN 0 = 0 THEN 0 ELSE 1/0 END c1 FROM src UNION ALL SELECT CASE WHEN key = 0 THEN 0 ELSE 1/key END c1 FROM src) r; -- 报错 FAILED: ODPS-0130071:[0,0] Semantic analysis exception - physical plan generation failed: java.lang.ArithmeticException: DIVIDE func result overflow, two params are 1.000000 and 0.000000
UNION ALL
第一个子句常量折叠报错。 - 解决方案。
建议将SQL中的
CASE WHEN
命令写到子查询中,并去掉/0
用法和无用的CASE WHEN
命令,如下所示。SELECT c1 END FROM ( SELECT 0 c1 END FROM src UNION ALL SELECT CASE WHEN key = 0 THEN 0 ELSE 1/key END) r;
- 问题描述。
ODPS-0010000 small table exceeds mem limit
- 问题描述。
MaxCompute1.0支持Multi-way Join优化,多个Join如果有相同Join Key,会合并到一个Fuxi Task执行,例如如下示例中的
J4_1_2_3_Stg1
。
如下所示增加MapJoin hint,MaxCompute1.0物理执行计划不会改变。即在MaxCompute1.0中优先应用Multi-way Join优化,并且可以忽略用户指定MapJoin hint。EXPLAIN SELECT t1.* FROM t1 JOIN t2 ON t1.c1 = t2.c1 JOIN t3 ON t1.c1 = t3.c1; MaxCompute1.0物理执行计划: In Job job0: root Tasks: M1_Stg1, M2_Stg1, M3_Stg1 J4_1_2_3_Stg1 depends on: M1_Stg1, M2_Stg1, M3_Stg1 In Task M1_Stg1: Data source: meta_dev.t1 In Task M2_Stg1: Data source: meta_dev.t2 In Task M3_Stg1: Data source: meta_dev.t3 In Task J4_1_2_3_Stg1: JOIN: t1 INNER JOIN unknown INNER JOIN unknown SEL: t1._col0, t1._col1, t1._col2 FS: output: None
在MaxCompute2.0中Optimizer会优先使用用户指定的MapJoin hint,对于上述例子,如果t1比较大的话,会出现如下错误。EXPLAIN SELECT /*+mapjoin(t1)*/ t1.* FROM t1 JOIN t2 ON t1.c1 = t2.c1 JOIN t3 ON t1.c1 = t3.c1; --MaxCompute1.0物理执行计划同上
FAILED: ODPS-0010000:System internal error - SQL Runtime Internal Error: Hash Join Cursor HashJoin_REL… small table exceeds, memory limit(MB) 640, fixed memory used …, variable memory used …
- 解决方案。
如果MapJoin不是期望行为,建议去掉MapJoin Hint。
ODPS-0130071 pt implicit convertion failed
- 问题描述。
srcpt是一个分区表,并有两个分区,DDL如下所示。
执行以下SQL,STRING类型pt列CREATE TABLE srcpt(key STRING, value STRING) PARTITIONED BY (pt STRING); ALTER TABLE srcpt ADD PARTITION (pt='pt1'); ALTER TABLE srcpt ADD PARTITION (pt='pt2');
IN
INT类型的常量,都会转成DOUBLE类型进行比较。
即使Project设置了SELECT key FROM srcpt WHERE pt IN (1, 2);
odps.sql.udf.strict.mode=true
参数,MaxCompute1.0不会报错,所有pt都会过滤掉,在MaxCompute2.0中会直接报如下错误。FAILED: ODPS-0130071:[0,0] Semantic analysis exception - physical plan generation failed: java.lang.NumberFormatException: ODPS-0123091:Illegal type cast - In function cast, value 'pt1' cannot be casted from String to Double.
- 解决方案。
建议避免STRING分区列和INT类型常量比较,将INT类型常量改成STRING类型。
ODPS-0130131 ctas if not exists
- 问题描述。
如果目标表已经存在,在MaxCompute1.0中不会做任何语法检查,在MaxCompute2.0则做正常的语法检查,这种情况会出现如下错误。
CREATE TABLE IF NOT EXISTS dual AS SELECT * FROM not_exist_table; --报错 FAILED: ODPS-0130131:[1,50] Table not found - table meta_dev.not_exist_table cannot be resolved
- 解决方案。
建议根据需求,删除不存在的表。
ODPS-0130071 post select ambiguous
- 问题描述。
在
order by
、cluster by
、distribute by
、sort by
等语句中,引用了名字冲突的列,在MaxCompute1.0中,系统会默认选取select列表中后一列作为操作对象,在MaxCompute2.0中则会报错,如下所示。select a, b as a from t order by a limit 10; --报错 FAILED: ODPS-0130071:[1,34] Semantic analysis exception - a is ambiguous, can be both t.a or null.a
- 解决方案。
为了不影响您的作业,建议修改SQL命令,如下所示。
select a as c, b as a from t order by a limit 10;
说明 名字虽然冲突但语义一样,虽然这种情况不会出现歧义,但是考虑到这种情况容易导致错误,建议您进行修改。
ODPS-0130071 having use select alias
- 问题描述。
SQL规范定义
GROUP BY
和HAVING
子句是SELECT子句之前阶段,HAVING中使用SELECT子句生成的列别名会出现如下报错。
其中SELECT id id2 FROM DUAL GROUP BY id HAVING id2 > 0; --报错 FAILED: ODPS-0130071:[1,44] Semantic analysis exception - column id2 cannot be resolved ODPS-0130071:[1,44] Semantic analysis exception - column reference id2 should appear in GROUP BY key
id2
为SELECT子句中新生成的列别名,不应该在Having子句中使用。在MaxCompute1.0中限制不够严格,不会报错。在MaxCompute2.0中会报错。 - 解决方案。
建议在Having中尽量不要使用SELECT子句中新生成的列别名。
ODPS-0130071 non boolean filter
- 问题描述。
MaxCompute中不允许布尔类型与其他类型之间隐式转换,但是在MaxCompute1.0中会允许用户在某些情况下使用Bigint作为过滤条件。这个问题将在MaxCompute2.0中修复,如果您的脚本中存在这样的过滤条件,请及时修改,如下所示。
select id, count(*) from dual group by id having id; --报错 FAILED: ODPS-0130071:[1,50] Semantic analysis exception - expect a BOOLEAN expression
- 解决方案。
将SQL命令修改为如下。
select id, count(*) from dual group by id having id <> 0;
ODPS-0130071 dynamic pt to static pt
- 问题描述。
在MaxCompute2.0中动态分区某些情况会被优化器转换成静态分区处理,如下转换过程。
- 转换前。
INSERT OVERWRITE TABLE srcpt PARTITION(pt) SELECT id, 'pt1' FROM dual;
- 转换后。
INSERT OVERWRITE TABLE srcpt PARTITION(pt='pt1') SELECT id FROM dual;
'${bizdate}'
,MaxCompute2.0语法检查阶段会报错,如下所示。
在MaxCompute1.0中因为LIMIT 0,SQL最终没有输出任何数据,动态分区不会创建,最终不报错。INSERT OVERWRITE TABLE srcpt PARTITION(pt) SELECT id, '${bizdate}' FROM dual LIMIT 0; --报错 FAILED: ODPS-0130071:[1,24] Semantic analysis exception - wrong columns count 2 in data source, requires 3 columns (includes dynamic partitions if any)
- 转换前。
- 解决方案。
建议使用合法的分区值,MaxCompute分区值说明请参见表操作。
ODPS-0123111 ODPS-0123091 ODPS-0121095 ODPS-0121065 invalid argument
出现如下报错。
错误原因均是参数错误,不外乎是参数格式错误或者是参数类型错误,请排查参数后进行修改。
1. format string does not match datetime string - in function to_date, datetime string value is xxxx and format string is xxxx
2. Semantic analysis exception - physical plan generation failed: java.lang.RuntimeException: ODPS-0123111:format string does not match datetime string - in function to_date, datetime string value is xxxx and format string is xxxx
3. Illegal type cast - in function cast, value xxxx cannot be casted from xxxx to xxxx
4. Semantic analysis exception - physical plan generation failed: java.lang.RuntimeException: ODPS-0121095:Invalid arguments - in function cast, string datetime's format must be yyyy-mm-dd hh:mi:ss, input string is:xxxx
5. Semantic analysis exception - physical plan generation failed: java.lang.RuntimeException: ODPS-0121065:Illegal argument - in function url_decode: xxxx
6. Argument value out of range - Regex group count is xxxx, but the specified group index is xxxx
7. millisecond delta overflow, delta = xxxxxxxx
说明 包括但不限于上面的报错。
- Case 1。
- 问题描述。
在如上命令中,select * from fake_table where partition_key = 20220702;
partition_key
是fake_table
表的String类型的分区列,但是在where
语句中对partition_key
和数字作比较,并且partition_key
的值不是数字类型,会报如下错误。
在Illegal type cast - in function cast, value '2020-01-01 01:01:01' cannot be casted from String to Double
partition_key
和20220702
比较过程中会将这两个值用cast
转换成Double类型再做比较,而partition_key
中的一些值没有办法从String转换为Double的类型。 - 解决方案。
建议将分区列的比较值改为字符串,如下所示。
select * from fake_table where partition_key = '20220702';
- 问题描述。
- Case 2。
- 问题描述。
在如上命令中,使用了select to_date(fake_date, 'yyyymmdd') from fake_table;
to_date
函数将fake_date
列的字符串转换为日期类型,但是字符串的格式不正确,会报如下错误。
报错是因为空字符串没有办法按照string does not match datetime string - in function to_date, datetime string value is '' and format string is 'yyyymmdd'
yyyymmdd
去解析而导致的。 - 解决方案。
建议检查作为参数的列的值,避免函数出现格式异常。
- 问题描述。
- Case 3。
- 问题描述。
在如上命令中,使用了select REGEXP_EXTRACT(fake_string,'xxxx(.*?)',2) from fake_table;
REGEXP_EXTRACT
函数来提取字符串,但是由于正则表达式和后面的group id
不匹配,会报如下错误。Argument value out of range - Regex group count is 1, but the specified group index is 2
- 解决方案。
建议检查作为参数正则表达式和其他参数是否匹配,如下所示。
select REGEXP_EXTRACT(fake_string,'xxxx(.*?)',1) from fake_table;
- 问题描述。
- Case 4。
- 问题描述。
在如上命令中,使用了select from_unixtime(fake_time/1000) from fake_table;
from_unixtime
,将Unix时间日期值转换为Datetime类型,但是由于换算错误,导致传入的值并不是秒数,数字过大不合法,会报如下错误。millisecond delta overflow, delta = 1648800491041000
- 解决方案。
建议检查
from_unixtime
的参数是否换算出错导致过大。
- 问题描述。
ODPS-0130071 group by duplicate key
- 问题描述。
在如上的命令中,select id, count(*) from fake_table a GROUP BY id, a.id;
group by
语句的两个Key含义一模一样,在这种情况下,会报出如下错误。Semantic analysis exception - repeated key xxxx in GROUP BY
- 解决方案。
检查
group by
子句并且删除重复的Key,重复的Key在实际运行中没有任何作用。
ODPS-0130071 function is ambiguous
- 问题描述。
在如上的命令中,如果用户定义了同名的UDF,并且函数签名分别为:select fake_udf(fake_decimal, fake_bigint) from fake_table;
STRING fake_udf(BIGINT arg0, BIGINT arg1)
。STRING fake_udf(DOUBLE arg0, BIGINT arg1)
。
Semantic analysis exception - function fake_udf is ambiguous with (DECIMAL(54,18), BIGINT), candidates are STRING evaluate(BIGINT arg0, BIGINT arg1); STRING evaluate(DOUBLE arg0, BIGINT arg1)
- 解决方案。
报错时的参数类型,备选UDF的函数签名都会通过报错信息给出。可以根据自身业务需要,来确定需要使用哪个函数,并且调整函数参数与要使用的函数签名一致。如上例可以改为:
select fake_udf(cast(fake_decimal as BIGINT), fake_bigint) from fake_table;
ODPS-0123131 java lang ClassCastException
- 问题描述。
在如上的命令中,select fake_udf(fake_date) as (fake_col1, fake_col2, fake_col3) from fake_table;
fake_udf
是典型的UDTF,而在定义fake_udf
的过程中不指定annotation并且没有覆盖resolve方法,会报如下错误。
按照接口约定,未指定Annotation并且没有覆盖Resolve方法,函数就可以接受任意参数并且返回任意参数,导致底层报错。Fuxi job failed - Failed in UDF/UDTF/UDAF xxxx class, at query location of line xxxx, column xxxx ODPS-0123131:User defined function exception - Traceback: java.lang.ClassCastException: java.util.Date cannot be cast to java.lang.Long
- 解决方案。
建议在UDF、UDTF、UDAF中指定Annotation并且重新实现Resolve方法。