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
    • 解决方案。

      建议去掉/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
    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
    如下所示增加MapJoin hint,MaxCompute1.0物理执行计划不会改变。即在MaxCompute1.0中优先应用Multi-way Join优化,并且可以忽略用户指定MapJoin hint。
    EXPLAIN
    SELECT /*+mapjoin(t1)*/ t1.*
    FROM t1 JOIN t2 ON t1.c1 = t2.c1
    JOIN t3 ON t1.c1 = t3.c1;
    
    --MaxCompute1.0物理执行计划同上
    在MaxCompute2.0中Optimizer会优先使用用户指定的MapJoin hint,对于上述例子,如果t1比较大的话,会出现如下错误。
    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如下所示。
    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');
    执行以下SQL,STRING类型ptIN INT类型的常量,都会转成DOUBLE类型进行比较。
    SELECT key FROM srcpt WHERE pt IN (1, 2);
    即使Project设置了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 bycluster bydistribute 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 BYHAVING子句是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语法检查阶段会报错,如下所示。
    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)
    在MaxCompute1.0中因为LIMIT 0,SQL最终没有输出任何数据,动态分区不会创建,最终不报错。
  • 解决方案。

    建议使用合法的分区值,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_keyfake_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_key20220702比较过程中会将这两个值用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

  • 问题描述。
    select fake_udf(fake_decimal, fake_bigint) from fake_table;
    在如上的命令中,如果用户定义了同名的UDF,并且函数签名分别为:
    • STRING fake_udf(BIGINT arg0, BIGINT arg1)
    • STRING fake_udf(DOUBLE arg0, BIGINT arg1)
    MaxCompute会因为无法选择两个UDF中的任何一个而出现如下报错。
    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方法,会报如下错误。
    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
    按照接口约定,未指定Annotation并且没有覆盖Resolve方法,函数就可以接受任意参数并且返回任意参数,导致底层报错。
  • 解决方案。

    建议在UDF、UDTF、UDAF中指定Annotation并且重新实现Resolve方法。