本文为您介绍外部表的常见问题。
问题类别 | 常见问题 |
OSS外部表 | |
性能问题 |
自定义Extractor在读取非结构化数据时,如果数据字段存在DATETIME类型,报错ODPS-0123131,如何解决?
问题现象
自定义Extractor在读取非结构化数据时,如果数据字段存在DATETIME类型(例如2019-11-11 06:43:36),会返回如下报错。
FAILED: ODPS-0123131:User defined function exception - Traceback: java.lang.IllegalArgumentException at java.sql.Date.valueOf(Date.java:143) at com.aliyun.odps.udf.example.text.TextExtractor.textLineToRecord(TextExtractor.java:194) at com.aliyun.odps.udf.example.text.TextExtractor.extract(TextExtractor.java:153) at com.aliyun.odps.udf.ExtractorHandler.extract(ExtractorHandler.java:120)
产生原因
查看指定位置的代码
Date.valueOf(parts[i])
,其中java.sql.Date.valueOf()
函数只支持形如"yyyy-[m]m-[d]d"
的STRING类型参数,不支持DATETIME时间类型参数。解决措施
引入Joda-Time依赖并在代码中增加导入信息。
--依赖。 <dependency> <groupId>joda-time</groupId> <artifactId>joda-time</artifactId> <version>2.10</version> </dependency> --导入信息。 import org.joda.time.DateTime; import org.joda.time.format.DateTimeFormat;
引入
DateTimeFormat.forPattern()
函数,将DATETIME类型的日期格式转化为STRING类型进行读取。record.setDate(index, new Date(DateTime.parse(parts[i], DateTimeFormat.forPattern("yyyy-MM-dd HH:mi:ss")).getMillis()));
使用示例如下。
通过MaxCompute客户端上传Extractor项目打包生成的JAR包。
add jar /Users/gary/big_data/odps/text_extractor/target/text_extractor-1.0-SNAPSHOT.jar
/Users/gary/big_data/odps/text_extractor/target/text_extractor-1.0-SNAPSHOT.jar
为生成JAR包的本地保存路径。通过MaxCompute客户端上传Joda-Time第三方JAR包。
add jar /Users/gary/.m2/repository/joda-time/joda-time/2.10/joda-time-2.10.jar
/Users/gary/.m2/repository/joda-time/joda-time/2.10/joda-time-2.10.jar
为Joda-Time第三方JAR包本地存放路径。上传测试数据至OSS指定的目录下。假设文件名为
video_play_log.txt
,示例数据如下。5c661071dba64d5080c91da085ff1073^音乐-点击-快进^26.12.04.68^2019-11-11 06:43:36
通过外部表读取数据。
select * from <project_name>.video_play_log;
读取结果如下。
+------+-------+---+----------------+ | uuid | action | ip | time | +------+-------+---+----------------+ | 5c661071dba64d5080c91da085ff1073 | 音乐-点击-快进 | 26.12.04.68 | 2019-11-11 06:43:36 | +------+-------+---+----------------+
在MaxCompute上访问OSS外部表,编写UDF本地测试通过,上传后报错内存溢出,如何解决?
问题现象
在MaxCompute上访问OSS外部表,编写UDF本地测试通过,上传后返回如下报错。
FAILED: ODPS-0123131:User defined function exception - Traceback: java.lang.OutOfMemoryError: Java heap space
设置如下参数后运行时间增加但依然报错。
set odps.stage.mapper.mem = 2048; set odps.stage.mapper.jvm.mem = 4096;
产生原因
外部表的对象文件太多,内存占用过大且未设置分区。
解决措施
使用小数据量查询。
将对象文件进行分区,以减少内存占用。
通过外部表处理OSS数据时,报错Inline data exceeds the maximun allowed size,如何解决?
问题现象
处理OSS数据时,报错
Inline data exceeds the maximum allowed size
。产生原因
OSS Store对于每一个小文件有一个大小限制,如果超过3 GB则报错。
解决措施
针对该问题,您可以通过调整以下两个属性进行处理。其原理是通过属性值调整执行计划,控制每个Reducer写入外部表OSS的数据大小,使得OSS Store文件不超过3 GB的限制。
set odps.sql.mapper.split.size=256; #调整每个Mapper读取数据的大小,单位是MB。 set odps.stage.reducer.num=100; #调整Reduce阶段的Worker数量。
如何在MaxCompute中使用OSS外部表读取JSON数据?
在MaxCompute中使用OSS外部表读取JSON数据的操作,请参见在MaxCompute中使用OSS外部表读取JSON数据。
如何通过OSS外部表将多个小文件输出为一个文件?
通过Logview日志,查看SQL的执行计划中最后一个是Reducer还是Joiner。如果是Reducer,则执行语句set odps.stage.reducer.num=1;
,如果是Joiner,则执行语句set odps.stage.joiner.num=1;
。
基于外部表执行SQL作业时,运行慢,如何解决?
基于外部表执行SQL作业时,运行慢的常见情况如下:
OSS外部表中的GZ压缩文件读取慢
问题现象
用户创建了一个OSS外部表,数据源为OSS中的GZ压缩文件,大小为200 GB。在读取数据过程中执行缓慢。
产生原因
由于Map端执行计算的Mapper数量过少,所以SQL处理慢。
解决措施
对于结构化数据,您可以设置以下参数调整单个Mapper读取数据量的大小,加速SQL执行。
set odps.sql.mapper.split.size=256; #调整每个Mapper读取Table数据的大小,单位是MB。
对于非结构化数据,您需要查看OSS外部表路径下的OSS文件是否只有1个。如果只有1个,由于压缩方式下的非结构化数据不支持拆分,所以只能生产1个Mapper,导致处理速度较慢。建议您在OSS对应的外部表路径下,将OSS大文件拆分为小文件,从而增加读取外部表生成的Mapper数量,提升读取速度。
使用SDK搜索MaxCompute外部表数据速度慢
问题现象
使用SDK搜索MaxCompute外部表数据速度慢。
解决措施
外部表仅支持全量搜索,所以较慢,建议您改用MaxCompute内部表。
查询外部表Tablestore数据慢
问题现象
查询外部表Tablestore的数据慢,同样的业务数据,1个实时写入Tablestore,1个定时写入MaxCompute,两个表结构和数据量一样。查询MaxCompute内部表耗时远小于查询Tablestore外部表。
解决措施
这种情况可能是对1份数据进行了多次计算,导致速度慢。相比每次从Tablestore远程读取数据,更高效快速的方法是先一次性把需要的数据导入到MaxCompute内部,转为MaxCompute内部表,再进行查询。