对接MaxCompute常见问题与诊断

本文为您介绍使用Hologres对接MaxCompute时的常见报错及解决方法。

基本概念

  • Hologres与MaxCompute的对比。

    对比项

    MaxCompute

    Hologres

    使用场景

    ETL(Extract-Transform-Load)加工,面向数据明细层(DWD,Data Warehouse Detail)和数据服务层(DWS,Data WareHouse Service)。

    交互式查询、在线数据服务,面向应用的数据服务(ADS)。

    用户使用

    异步的执行作业。

    同步的Query。

    集群资源

    共享大集群,SaaS模式。

    独享集群,PaaS模式。

    计算引擎

    基于Job Execution模型,将作业转化为Stage,每个Stage按需申请计算资源,执行过程中通过File持久化。

    基于MPP模型,精细化内存资源管理,执行引擎常驻内存,用户态细粒度SQL算子调度,计算不落盘。

    调度方式

    进程级别,运行时按需申请、分配。

    轻量级线程,资源启动时预留。

    扩展性

    几乎不受限制。

    复杂查询尽量避免跨多节点数据Shuffle。

    存储格式

    列式。

    行式、列式、行列共存。

    存储成本

    基于Pangu,成本低。

    基于Pangu,利用SSD做缓存加速,成本相对高。

    接口标准

    MaxCompute SQL,类Hive。

    PostgreSQL。

  • Hologres外部表和内部表的适用场景

    • 新建外部表直接加速查询

      外部表不存储数据,数据存储在MaxCompute中,且外部表没有索引,全靠CPU资源进行计算,因此外部表比较适用于小数据量,低QPS(Queries-per-second)的查询。

    • 导入数据至Hologres内部表进行加速查询

      内部表的数据存储在Hologres中,当有数据更新、复杂查询、高QPS的查询时,建议导入内部表,能充分发挥Hologres底层的性能优势。

性能调优

性能退化:MaxCompute外部表发生Schema Evolution之后,查询性能大幅下降

  • 下降原因:Hologres加速查询MaxCompute外部表默认走HQE直读链路,当MaxCompute外部表结构发生变更后,会回退到SQE链路,访问链路更长,导致查询性能下降。

  • 解决方法:通过hologres.hg_query_log来查询慢Query。如果engine_type为SQE,可以确认MaxCompute Schema Evolution链路切换为SQE导致性能下降。可以尝试重新构建需要进行表结构变更的MaxCompute外部表来解决该问题。

常见报错

报错:SERVER_INTERNAL_ERROR message: GetRecordBatch() is not implemented.

查询MaxCompute外表时报错:query next from foreign table executor failed, GetRecordBatch() is not implemented

  • 报错原因:当前MaxCompute的表类型不是Cfile类型的表,Hologres暂不支持该类型的表。

  • 解决方法:在查询数据SQL前添加如下GUC。

    set hg_experimental_enable_access_odps_with_table_api =on;

报错:ERROR: not an ORC file

查询外部表时报错:ERROR: status { code: SERVER_INTERNAL_ERROR message: "hos_exception: Invalid argument: ../../../src/OrcFileMetaHelper.cc(234)-<operator()>: not an ORC file

  • 报错原因:MaxCompute的表是Stream表,数据是通过Tunnel等流式写入,当前Hologres直读MaxCompute外部表时暂不支持查询该状态的表。

  • 解决方法:在查询数据SQL前添加如下GUC。

    set hg_experimental_enable_access_odps_with_table_api=on;
    set hg_experimental_enable_access_odps_orc_via_holo =off;

报错:specified partitions count in MaxCompute table: exceeds the limitation of 512, please add stricter partition filter or set axf_MaxCompute_partition_limit.或者Build desc failed: Exceeds the partition limitation of 512, current match xxx partitions.

  • 报错原因:

    当前Hologres支持查询最多分区数为512个,查询超过此限制。

  • 解决方法:

    • 请添加分区过滤条件,使一次查询不超过512个分区。

    • 请将数据导入Hologres内部表,则没有分区限制,详情请参见使用SQL导入MaxCompute的数据至Hologres

    • 使用如下命令调整每次Query命中的分区数,默认为512,最大为1024,不建议调整太大,否则会影响查询性能。

      -- V1.1及以上版本
      set hg_foreign_table_max_partition_limit = 128;
      -- V0.10版本
      set hg_experimental_foreign_table_max_partition_limit = xxx ;
      说明

      如果MaxCompute配置了多级分区,会按照最细粒度分区单位进行分区命中计数。

报错:Build desc failed: Exceeds the scan limitation of 200 GB, current scan xxx GB.

  • 报错原因:

    Hologres中默认最大的底层数据扫描量为200GB,此数据量是命中MaxCompute分区之后的扫描数据量,和MaxCompute自身存储数据量无关,查询超出此限制导致报错。

  • 解决方法:

    • 增加过滤条件,命中更少的分区,使一次Query的扫描数据量在200GB以内。

    • 请将MaxCompute表数据导入至Hologres中,再进行查询,详情请参见使用SQL导入MaxCompute的数据至Hologres

    • (不推荐)使用set hg_experimental_foreign_table_max_scan_size = xxx;命令设置参数调大数据量限制(其中xxx可以替换为业务的数据量,如400,单位为GB)。但是过分调大外部表数据量限制,可能无法得到预期的性能,也可能造成实例OOM(Out Of Memory),影响正常使用。

报错:query next from foreign table executor failed, Not implemented.

  • 报错原因:MaxCompute表数据写入时使用Streaming Tunnel的方式写入,写入命令为tunnel.createStreamUploadSession。Hologres读取数据时需要开启两个GUC。

  • 解决方法:

    • 添加如下两个配置项。

      说明

      仅Hologres V1.3及以上版本支持该GUC。

      set hg_experimental_enable_access_odps_with_table_api=on;
      set hg_experimental_enable_access_odps_orc_via_holo =off;
    • 如果实例版本低于V1.3版本,建议在MaxCompute侧停止streaming写入,然后通过以下语句对数据进行Merge:

      set odps.merge.task.mode=sql;
      set odps.merge.lock.expire.time=0;
      ALTER TABLE tablename [PARTITION] MERGE SMALLFILES;

报错:Build desc failed: failed to check permission: Currently not supported table type "view".

报错原因:目前暂时不支持MaxCompute的View。

报错:Build desc failed: failed to get foreign table split:MaxCompute-0010000: System internal error - get input pangu dir meta fai.

  • 报错原因:

    Hologres读取MaxCompute的配置未及时更新。

  • 解决方法:

    请过几分钟重试,若是重试好几次都未成功,请联系技术支持处理。

报错:ERROR: Query:[xxx] Build desc failed: failed to get foreign table split:ERPC_ERROR_CONNECTION_CLOSED.

  • 报错原因:

    MaxCompute小文件过多,导致请求的META超过远程过程调用协议(RPC,Remote Procedure Call Protocol)1GB的最大限制。

  • 解决方法:

    • 请执行以下命令进行小文件合并。

      set MaxCompute.merge.task.mode=sql;
      set MaxCompute.merge.lock.expire.time=0;
      ALTER TABLE <tablename> [PARTITION] MERGE SMALLFILES;
    • HologresV0.10.21及以上版本已优化,请升级Hologres实例,详情请参见实例升级

    • 请联系MaxCompute技术支持从源头解决,如果数据量不大可直接将数据写入Hologres。

报错:ERROR: status { code: SERVER_INTERNAL_ERROR message: "hos_exception: IO error: Failed to execute pangu open normal file, err: PanguParameterInvalidException" }.

  • 报错原因:

    Hologres HQE不支持直读MaxCompute Pangu加密数据。

  • 解决方法:

    请执行 ALTER DATABASE <dbname> SET hg_experimental_enable_access_odps_orc_via_holo = false;命令将外部表的执行引擎修改为SQE,使用SQE访问MaxCompute加密数据,该配置是数据库级别配置,需要重新创建连接才能生效;您也可执行Session级别设置:SET hg_experimental_enable_access_odps_orc_via_holo = false;

报错:failed to import foreign schema:Failed to get MaxCompute table:Not enable schema evolution.

  • 报错原因:

    对MaxCompute表的元数据做了修改。

  • 解决方法:

    • 请升级Hologres实例版本至V1.3及以上版本,通过加入实时数仓Hologres交流群申请升级实例或自助升级,加群方式请参见如何获取更多的在线支持?

    • 更新了MaxCompute外部表Schema之后(例如增加列、删除列操作),请执行IMPORT FOREIGN SCHEMA来做刷新。

    • 如果执行了IMPORT FOREIGN SCHEMA还报错的话,请重新建一次MaxCompute的表,再建外部表,因为MaxCompute修改Schema之后进入到schema evolution状态,Hologres无法读取这种状态的表。

报错:Open ORC file failed for schema mismatch. Reader schema:

  • 报错原因:

    MaxCompute的表为ORC格式,表的DECIMAL类型存储方式改变(一般是MaxCompute新加了DECIMAL字段或者MaxCompute做了灰度配置变更),导致Hologres读MaxCompute的DECIMAL类型出错。

  • 解决方法:

    • 请执行set MaxCompute.storage.orc.enable.binary.decimal=false命令,重新导下MaxCompute数据。

    • 请将MaxCompute的表的DECIMAL类型改为DOUBLE类型,再重新刷新一遍数据。

报错:failed to import foreign schema:Failed to get MaxCompute table:Not enable acid table.

  • 报错原因:

    MaxCompute表是事务(Transactional)表。

  • 解决方法:

    当前不支持MaxCompute的Transactional表,建议改为普通表。

报错:Request denied, may caused by server busy.

  • 报错原因:

    外部表资源占满,CPU用量严重超出。

  • 解决方法:

    • 请优化SQL,使SQL更加充分合理地使用资源,详情请参见优化MaxCompute外部表的查询性能

    • 降低并发度。

      1. 使用show hg_foreign_table_executor_max_dop;命令查看当前配置。

      2. 使用如下命令降低并发度,推荐调整为当前配置的一半。

        -- 语法示例
        set hg_foreign_table_executor_max_dop = <并发数>; 
        -- 使用示例 
        set hg_foreign_table_executor_max_dop = 18;

        并发数:外部表单个执行节点读取外部表数据的并发度,默认值为256,取值范围为0-1024。修改后的风险: 并发度太大可能造成实例OOM,导致导入、查询失败,甚至实例重启,以至于服务不可用。并发度太小会导致外表查询、外表导入内表性能较差。

    • 请导入数据至Hologres内部表,内部表可以设置索引,使查询性能更好,详情请参见使用SQL导入MaxCompute的数据至Hologres

导入数据报错:Query executor exceeded total memory limitation xxxxx: yyyy bytes used.

  • 报错原因:

    数据量太大或者导入逻辑太复杂,导致超出了内存限制。(实例由多个节点组成,一个节点标准的内存上限是64GB,节点内存会分为三部分,三分之一用于计算,三分之一用于缓存,三分之一用于元数据。这里的报错是计算内存超出了限制。)

  • 解决方法:

    1. 查看执行计划

      可以执行explain analyze sql;命令查看执行计划中具体的数据行数。当导入Query包含查询,但部分表没有analyze,或者analyze过,但数据又有更新导致不准确,导致查询优化器决策连接顺序有误,会引起内存开销过高。

      对所有参与的内表、外表执行analyze tablename;命令,更新表的统计元信息,可以帮助查询优化器生成更优的执行计划。

    2. 设置单行导入条数

      当表的列数较多,单行数据量较大时,单次读取的数据量会更大,通过在SQL前加以下参数来控制单次读取数据的行数,可以有效减少OOM情况。

      set hg_experimental_query_batch_size = 1024;  -- 默认值为8192
      insert into holo_table select * from mc_table;
    3. 降低导入的并发度。

      降低导入并发度,也会有效减少导入过程中的内存开销,并发度通过参数hg_foreign_table_executor_max_dop控制,默认为实例的Core数,可以在导入时设置更小的参数,降低导入的内存使用。

      set hg_foreign_table_executor_max_dop = 8;
      insert into holo_table select * from mc_table;
    4. 排查外表重复数据是否过多。

      如果以上操作都做完了,还是导入不了,如果使用的是insert on conflict命令,请排查是否外表重复数据太多,重复数据太多也会导致导入性能不好,可以在MaxCompute做重复数据去重,再进行导入,详情请参见多行数据合并为一行数据

    5. 升级新版本动态调整内存。

      Hologres从V1.1.24版本开始,会对内存进行动态调整,后台会实时刷新当前内存水位,若是有空闲,则会分配更多内存给计算使用,请升级Hologres至最新版本,具体操作请参见实例升级

    6. 扩容。

      如果以上操作都做完了,导入数据还是不成功,请对Hologres扩容,详情请参见升配

报错:Timestamp overflow detected while converting timestampfrom orc VectorBatch to arrow.

  • 报错原因:

    在MaxCompute表中有TIMESTAMP类型,使用Tunnel写入后TIMESTAMP精度会变成纳秒,目前Hologres暂不支持精度为纳秒的TIMESTAMP。

  • 解决方法:

    • 在MaxCompute中将TIMESTAMP类型转换为DateTime类型。

    • Hologres实例升级版本到 V1.1.70及以上版本。

报错:You have NO privilege 'MaxCompute:Select' on xxx.

  • 报错原因:

    当前账号不具备MaxCompute表的查询(Select)权限。

  • 解决方法:

    请联系MaxCompute管理员在MaxCompute中授予当前账号查询表(Select)的权限,具体操作请参见MaxCompute权限

报错:The sensitive label of column 'xxx' is 2, but your effective label is 0.

  • 报错原因:

    当前账号只有MaxCompute表的部分字段权限。

  • 解决方法:

    • 核对有权限的账号和报错的账号是否为同一个账号,若确实没有权限,可以去申请MaxCompute的权限,或者只过滤有权限的字段查询。获取MaxCompute表全部字段的权限,具体操作请参见授权。

    • 若是有权限,并且也只查询了有权限的字段,在实例比较老的版本可能存在缺陷,您可以在执行的Query前增加如下命令解决报错问题。

      set hg_experimental_enable_MaxCompute_executor=on;  
      set hg_experimental_enable_query_master=on;

报错:query next from foreign table executor failed validate userinfao

  • 报错原因:

    未正确对Hologres的AliyunHologresEncryptionDefaultRole进行授权,或者因为缓存的原因,授权未超过3小时也可能偶发出现此报错。

  • 解决方法:

    对账号授权AliyunHologresEncryptionDefaultRolePolicy角色,详情请参见查询MaxCompute加密数据(BYOK模式)

查询外部表速度慢如何解决?

建议优化SQL,详情请参见优化MaxCompute外部表的查询性能

查询外部表报错:You have NO privilege 'odps:Select' on xxx

  • 问题现象

    当您在Hologres管理控制台创建外部表之后,查询外部表时报错提示“You have NO privilege 'odps:Select' on xxx”。

  • 问题原因

    当前账号不具备MaxCompute表的查询(Select)权限。

  • 解决方法

    需要MaxCompute管理员在MaxCompute中授予当前账号查询表(Select)的权限,具体操作请参见MaxCompute权限

查询外部表报错:The sensitive label of column 'xxx' is 2, but your effective label is 0

  • 问题现象

    当您在Hologres管理控制台创建外部表之后,查询外部表时报错提示“The sensitive label of column 'xxx' is 2, but your effective label is 0”。

  • 问题原因

    当前账号只有MaxCompute表的部分字段权限。

  • 解决方法

    您可以选择如下三种方法中的一种来解决该问题:

    • (推荐)建议您搜索加入实时数仓Hologres交流群申请将当前实例版本升级至V0.8,详情请参见如何获取更多的在线支持?

    • 您可以在执行的Query前增加如下参数解决报错问题。

      set hg_experimental_enable_odps_executor=on; 
      set hg_experimental_enable_query_master=on;
    • 获取MaxCompute表全部字段的权限,具体操作请参见MaxCompute权限

跨project访问MaxCompute表报错:You have NO privilege 'odps:Select' on xxx

  • 问题现象

    当前账号已经具备MaxCompute表查询权限,但是跨project访问MaxCompute表报错”You have NO privilege 'odps:Select' on xxx“。

  • 问题原因

    若是当前账号已经具备MaxCompute已经有表的查询权限,跨project访问MaxCompute表还是报错,则MaxCompute当前可能采用的是package授权,您需要添加SQL语句解决该问题。

  • 解决方法

    当前如果MaxCompute是project授权方式,在Hologres中,您可以在SQL前添加如下参数解决。

    // V0.7版本的实例请执行以下语句授权
    set seahawks.seahawks_internal_current_odps_project='holoprojectname';
    //V0.8版本的实例请执行以下语句授权
    set hg_experimental_odps_current_project_name = 'holoprojectname';

创建外部表报错:You have NO privilege 'odps:List' on xxx

  • 问题现象

    当您在Hologres管理控制台使用HoloWeb或DataStudio可视化创建外部表时报错提示“You have NO privilege 'odps:List' on xxx”。

  • 问题原因

    当前账号在MaxCompute中不具备查看所有表(List)的权限。

  • 解决方法

创建外部表时报错:Access denied by project ip white list: sourceIP:'xxxx' is not in white list. project: xxxx

  • 问题现象

    当您在Hologres管理控制台使用HoloWeb创建外部表时报错提示“Access denied by project ip white list: sourceIP:'xxxx' is not in white list. project: xxxx”。

  • 问题原因

    当前MaxCompute集群设置了白名单访问,Holoweb不在白名单内。

  • 解决方法

    当MaxCompute项目开启白名单功能时,仅允许白名单内的设备访问项目空间;非白名单内的设备访问项目空间时,即使拥有正确的AccessKey ID及AccessKey Secret,也无法通过鉴权。因此需要将报错信息中的IP设置为白名单才可以创建外表,具体操作请参见管理IP白名单

创建外部表时报错:You don't exist in project xxx

  • 问题现象

    当您在创建外部表时报错提示“You don't exist in project xxx”。

  • 问题原因

    执行创建外部表的账号不具有访问对应MaxCompute Project的权限。

  • 解决方法

    请先确认需要访问的MaxCompute Project名称,如果Project名称错误请先换成正确的Project名。如果Project名称正确仍然报同样的错误,需要前往MaxCompute中给报错的账号授权,详情请参见权限概述