迎留言!
数据问题
Q:使用Tunnel Java SDK上传数据,上传数据可以自动分配到各个分区吗?
A:目前Tunnel是无法自动上传数据并自动分配到各个分区的:每一次上传只支持数据上传到一张表或表的一个分区,有分区的表一定要指定上传的分区,多级分区一定要指定到末级分区。关于JAVA SDK可参考:Java SDK。
Q:使用Tunnel Java SDK上传数据,如果是分区表,SDK能够动态根据数据创建不同的分区吗?
A:分区需要首先创建好,在使用SDK上传数据时指定。您也可以先把数据上传到MaxCompute上的表中,再用SQL语句动态分区。
Q:使用Tunnel命令行tunnel upload D:\test test/pt="time"
在 DataIDE上进行分区上传为什么报错:FAILED: error occurred while running tunnel command
?
A:DataIDE是不支持MaxCompute Tunnel命令行工具的upload语句的。
Q:利用Tunnel命令行工具上传数据时,共分为50个block,开始一切正常,但是在第22个block时,出现Upload fail,retry 5次后,直接跳过开始上传第23个block,为什么会发生这种情况?
A:Block 的概念:一个 block 对应一个HTTP request,多个 block 的上传可以并发而且是原子的,一次同步请求要么成功要么失败,不会污染其他的 block。
重传retry有次数的限制的,当重传的次数超过了这个限制,就会继续上传下一个block。上传完成后,可以通过select count(*)
语句,检查是否有数据丢失。
Q:本地服务器每天采集的网站日志有10GB,需要上传至MaxCompute,在使用Tunnel Upload命令上传达到的速度约300KB/S 如何提升上传速度?
A:Tunnel Upload命令上传是不设速度限制的。上传速度的瓶颈在网络带宽以及服务器性能。为了提升性能,可以考虑分区分表,在多台ECS上传下载数据。
Q:如何在Shell脚本中将一个TXT文件中的数据上传到MaxCompute的表中, 即把这两条命令组合成一条?命令如下:
/odpscmd/bin/odpscmd
tunnel upload "$FILE" project.table
A:可参考客户端设置命令行客户端的启动参数,在Shell中启动命令是:/odpscmd/bin/odpscmd -e “tunnel upload "$FILE" project.table”
Q:MaxCompute使用TunnelUpload命令上传数据,如果数据里面有回车或空格为什么上传失败?
A:如果数据里有回车或空格,可以给数据设置不同与回车或空格的分隔符后,用-rd和-fd指定对应的分隔符实现数据的上传。如果无法更换数据中的分隔符,可以将数据作为单独一行上传,然后使用UDF解析。
例如下列数据中包含回车,使用“,”作为列分隔符rd,使用“@”作为行分隔符fd,可以正常上传:
数据内容:
shopx,x_id,100@
shopy,y_id,200@
shopz,z_i
d,300@
上传命令:odps@ MaxCompute_DOC>tunnel u d:\data.txt sale_detail/sale_date=201312,region=hangzhou -s false -fd "," -rd "@";
上传结果:
+-----------+-------------+-------------+-----------+--------+
| shop_name | customer_id | total_price | sale_date | region |
+-----------+-------------+-------------+-----------+--------+
| shopx | x_id | 100.0 | 201312 | hangzhou |
| shopy | y_id | 200.0 | 201312 | hangzhou |
| shopz | z_id
d | 300.0 | 201312 | hangzhou |
+-----------+-------------+-------------+-----------+--------+
Q:MaxCompute使用TunnelUpload命令上传数据,使用的","进行列分割, 现在description字段里, 数据有逗号, 或者"|"符号, 这种情况怎么分割?
A:如果数据描述字段内本身有逗号,可以考虑转换数据的分隔符为其他符号,再通过-fd
指定为其他分隔符进行上传,举例如下:
用户有一个岗位需求的EXCEL数据在Windows环境下需要通过Tunnel Upload命令上传,表格内本身包含“,”。首先可通过Windows环境设置EXCEL转换为CSV文件的默认分隔符:Win7系统在控制面板 时钟、语言和区域 选择 更改日期、时间或数字格式,点击其他设置。本例中考虑到原始数据中没有“字符,设置分隔符为
”,如下图所示:
完成设置后,使用EXCEL将数据另存为CSV文件,并且利用Notepad++等文本编辑工具转码为UTF-8编码(Tunnel默认使用的编码格式),检查是否文件分隔符已变成“$”:标题$所在地$薪资$公司$公司介绍链接$公司类型$公司规模$所属行业$工作经验$学历$所招人数$发布时间$标签$职位信息$上班地址$公司信息$页面网址$采集时间
使用TunnelUpload命令上传数据并指定分隔符(需预先在MaxCompute上创建好表格),即可成功上传:
odps@ MaxCompute_DOC>tunnel u d:\12JD.CSV JD2 -s false -fd "$";
Upload session: 201808201531180d47df0b0b18fa45
Start upload:d:\12JD.CSV
Using \r\n to split records
Upload in strict schema mode: true
Total bytes:111028 Split input to 1 blocks
2018-08-20 15:31:18 upload block: '1'
2018-08-20 15:31:18 upload block complete, blockid=1
upload complete, average speed is 108.4 KB/s
OK
Q:MaxCompute使用Tunnel Upload命令上传数据。Tunnel Upload命令默认使用逗号分割的,但数据CSV文件也是用逗号分割的:文件里面有一列数据里面本身就含有用引号引起来的逗号。这种情况如何处理?
A:CSV文件使用其他分隔符,可以通过 -fd参数指定。
通常来说,如果数据例有很多符号,可能与分隔符发生冲突,可以自定义数据中分隔符来避免冲突,比如#@
@ 或者)*#@
@$。
Q:MaxCompute使用Tunnel Upload命令上传数据时失败,内存溢出报错java.lang.OutOfMemoryError:Java heap space
是什么原因?
A:从报错上看是数据上传的时候的内存溢出了。目前TunnelUpload命令是支持海量数据的上传的,如果出现内存溢出,可能是因为数据的行分隔符和列分隔符设置错误,导致整个文本会被认为是同一条数据,缓存到内存里再做split,导致内存溢出报错。
这种情况下可以先拿少量的数据测试,把-td及-fd调试过了后再上传拿全量的数据。
Q:MaxCompute使用Tunnel Upload命令上传数据,需要上传很多个数据文件到一个表中,是否有方法写一个脚本就可以把文件夹下的所有数据文件循环上传上去?
A:TunnelUpload命令上传支持文件或目录(指一级目录)的上传。
例如下述命令,上传数据为文件夹d:data,上传命令为:odps@ MaxCompute_DOC>tunnel u d:\data sale_detail/sale_date=201312,region=hangzhou -s false;
详情请参见Tunnel命令操作。
Q:导入文件夹会报错:字段不匹配colum mismatch
,但是这个文件夹下的文件单独导入时又是可以导入的,是因为文件太大吗?
A:这种情况下,可以在upload命令后加上-dbr=false -s true
对数据格式进行验证。出现column mismatch通常是由于列数对不上导致的:可能性较大的原因包括列分隔符设置的不对或文件的最后有空行,导致空行进行分隔符分割的时候分不出那么多列。
Q:MaxCompute使用Tunnel Upload命令上传两个文件,上传完第一个文件命令结束之后,第二个文件不会上传是什么原因?没有报错信息,就是第一个文件上传之后第二个文件上传命令不执行了。上传命令如下:
D:\odps\bin\odpscmd.bat -e"tunnel upload d:\data1.txt sale_detail/sale_data=201312 -fd="$" -mbr=5 --scan=true; "
D:\odps\bin\odpscmd.bat -e"tunnel upload d:\data2.txt sale_detail/sale_data=201312 -fd="$" -mbr=5 --scan=true; "
A:当使用老版本MaxCompute命令行客户端,上传参数有--scan
的时候,续跑模式的参数传递有问题,将--scan=true
去掉重试即可。
Q:MaxCompute使用Tunnel Upload命令把一个目录下的所有文件上传到一个表里,并且想要自动建立分区,具体的命令是 tunnel upload /data/2018/20180813/*.json app_log /dt=20180813 -fd '@@' -acp true;
,执行报错:
Unrecognized option: -acp
FAILED: error occurred while running tunnel command
A:出现这种报错通常是因为是用了不支持的命令或字符。MaxCompute使用Tunnel Upload命令上传不支持通配符及正则表达式。
Q:MaxCompute使用Tunnel Upload命令上传文件数据报错,是否有像MySQL的-f的强制跳过错误数据继续进行上传的命令?
A:出现这种错误是因为数据格式问题,例如数据类型不对,可参考Tunnel命令操作,使用-dbr true
参数忽略脏数据(多列,少列,列数据类型不匹配等情况)。-dbr参数默认用false,表示不忽视脏数据,当值为true时,将不符合表定义的数据全部忽略。
Q:MaxCompute使用Tunnel Upload命令上传文件数据报错如下是为什么?
java.io.IOException: RequestId=XXXXXXXXXXXXXXXXXXXXXXXXX, ErrorCode=StatusConflict, ErrorMessage=You cannot complete the specified operation under the current upload or download status.
at com.aliyun.odps.tunnel.io.TunnelRecordWriter.close(TunnelRecordWriter.java:93)
at com.xgoods.utils.aliyun.maxcompute.OdpsTunnel.upload(OdpsTunnel.java:92)
at com.xgoods.utils.aliyun.maxcompute.OdpsTunnel.upload(OdpsTunnel.java:45)
at com.xeshop.task.SaleStatFeedTask.doWork(SaleStatFeedTask.java:119)
at com.xgoods.main.AbstractTool.excute(AbstractTool.java:90)
at com.xeshop.task.SaleStatFeedTask.main(SaleStatFeedTask.java:305)
A:这个错误的提示是当前已经是在上传或下载中,所以无法再操作。
Q:MaxCompute使用Tunnel SDK上传文件数据报错重复提交是为什么?
RequestId=20170116xxxxxxx, ErrorCode=StatusConflict, ErrorMessage=You cannot complete the specified operation under the current upload or download status. java.io.IOException: RequestId=20170116xxxxxxx, ErrorCode=StatusConflict, ErrorMessage=You cannot complete the specified operation under the current upload or download status.
at com.aliyun.odps.tunnel.io.TunnelRecordWriter.close(TunnelRecordWriter.java:93)
A:由上述报错可见,这个问题是在准备close这个writer时出现的,可能有以下几种情况:
- 对一个已经关闭的writer做了关闭操作。
- 这个writer对应的session已经关闭。
- 该session已经被提交过。
可以针对上述可能出现的原因进行排查,比如打印当前writer和session的状态。
Q:MaxCompute使用Tunnel SDK上传数据时,编写完UDF打成Jar包后上传,对Jar包大小有要求吗?
A:Jar包不能超过10M, 如果Jar超过10M,建议转用MaxCompute Tunnel Upload命令行上传数据。
Q:MaxCompute使用Tunnel Upload命令行上传数据,对数据大小有限制吗?
A:Tunnel Upload命令行通常不会限制需上传的数据大小。
Q:MaxCompute使用Tunnel Upload命令行上传CSV文件,如何跳过第一行表头上传其他数据?
A:建议使用-h true
参数,跳过table header.
Q:使用Tunnel批量数据通道SDK来导入MaxCompute数据库是否有分区限制?
A:使用Tunnel批量数据通道SDK来导入MaxCompute数据库。目前支持的是6万个分区。
分区数量过多,会给统计和分析带来极大的不便。MaxCompute会限制单个作业中最多不能超过一定数量的instance。作业的instance和用户输入的数据量和分区数量是密切相关的,所以建议首先评估下业务,选择合适的分区策略,避免分区过多带来的影响。
关于分区表的更多信息请参考分区。
此外,MaxCompute也支持通过Python SDK来进行Tunnel批量上传,请参考Python SDK中的数据上传/下载配置。
Q:要一次性上传8000W的数据,最后在odps tunnel recordWriter.close()
时报错,报错内容如下:
ErrorCode=StatusConflict, ErrorMessage=You cannot complete the specified operation under the current upload or download status.
A:这个报错说明session的状态错误,建议重新创建个session重新上传一下数据。从报错上看,很可能是前面的操作里已经close了这个session,或者已经commit了。对于不同的分区,需要每个分区都是单独的一个session。
为了防止多次commit导致的这种报错,可以先检查数据上传是否已经传成功,如果失败的话重新上传一次。可参考多线程上传示例。
Q:如何使用TunnelBufferedWriter规避使用Tunnel SDK进行批量数据上传出错的问题?
A:MaxCompute Java SDK在0.21.3-public版本之后新增了BufferredWriter的SDK,简化了数据上传,并且提供了容错功能。
BufferedWriter对用户隐藏了block的概念:从用户角度看,就是在session上打开一个writer然后进行写记录即可。具体实现时,BufferedWriter先将记录缓存在客户端的缓冲区中,并在缓冲区填满之后打开一个http连接进行上传。
BufferedWriter会尽最大可能容错,保证数据上传上去。使用方法请参考BufferedWriter使用指南。
Q:MaxCompute使用TunnelUpload命令行上传CSV文件,为什么导入成功后原文本中有很大一部分内容莫名消失,被“ - ”取代?
A:这种情况很可能是因为数据编码格式不对导致上传到表的数据不对,或者是分隔符使用错误。建议规范原始数据后上传.
Q:MaxCompute使用Tunnel Upload命令行上传是否支持引用一个表的配置?
A:可以shell脚本方式执行Tunnel Upload命令行上传实现。可通过/odpscmd/bin/odpscmd -e
执行脚本,并在脚本内粘贴表格配置。
Q:MaxCompute使用Tunnel SDK上传数据时,经常会发现Select查询慢,SQL语句的执行性能不好的情况。
遇到类似情况,可能原因是MaxCompute小文件过多,从而影响性能导致的。如何处理小文件过多的问题?
A:
小文件产生的原因:
MaxCompute使用的分布式文件系统是按块Block存放,通常文件大小比块大小小的文件(默认块大小为64M),叫做小文件。
目前MaxCompute有以下场景可以产生小文件:
- Reduce计算过程会产生大量小文件;
- Tunnel数据采集过程中会生成小文件;
- Job执行过程中生成的各种临时文件、回收站保留的过期的文件等,主要分类为:
- TABLE_BACKUP:回收站中超过保留天数的表
- FUXI_JOB_TMP:作业运行临时目录
- TMP_TABLE:作业运行中产生的临时表
- INSTANCE:作业运行时保留在meta表中的日志
- LIFECYCLE:超过生命周期的的数据表或分区
- INSTANCEPROFILE:作业提交及执行完成后的profile信息
- VOLUME_TMP:没有meta信息,但在pangu上有路径的数据
- TEMPRESOURCE:用户自定义函数使用的一次性临时资源文件
- FAILOVER:系统发生failover时保留的临时文件
小文件过多会带来以下影响:
- 影响Map Instance性能:默认情况下一个小文件对应一个instance,造成浪费资源,影响整体的执行性能。
- 过多的小文件给分布式文件系统带来压力,且影响空间的有效利用,严重时会直接导致文件系统不可用。
查看表中的小文件数量命令:desc extended + 表名
小文件处理方式
不同原因产生的小文件,需要有不同的处理方法:
(1)Reduce过程中产生的小文件
使用insert overwrite源表(或分区),或者写入到新表删除源表。
(2)Tunnel数据采集过程中产生的小文件
- 调用Tunnel SDK时,当buffer达到64MB时提交一次;
- 使用console时避免频繁上传小文件,建议积累较大时一次性上传;
- 如果导入的是分区表,建议给分区设置生命周期,过期不用的数据自动清理;
- Insert overwrite源表(或分区):
ALTER合并模式,通过命令行进行合并:set odps.merge.cross.paths=true;
set odps.merge.max.partition.count=100; --默认优化10个分区,此时设置为优化100个分区。
ALTER TABLE tablename [PARTITION] MERGE SMALLFILES;
- 临时表
在用临时表建议创建时都加上生命周期,到期后垃圾回收自动回收。
Q:MaxCompute使用Tunnel Upload命令行上传数据,如果数据使用空格作为列分隔符,或需要对数据做正则表达式过滤时该如何处理?
A:Tunnel Upload命令行不支持正则表达式。如果数据使用空格作为列分隔符,或需要对数据做正则表达式过滤时可借助MaxCompute的UDF自定义函数功能。
首先,将数据作为单列数据上传。本例中原始数据如下,列分割符为空格,行分隔符为回车,并且需要取的部分数据在引号内,部分数据例如"-"需要被过滤。这种复杂的需求可通过正则表达式实现。
10.21.17.2 [24/Jul/2018:00:00:00 +0800] - "GET https://help.aliyun.com/document_detail/73477.html" 200 0 81615 81615 "-" "iphone" - HIT - - 0_0_0 001 - - - -
10.17.5.23 [24/Jul/2018:00:00:00 +0800] - "GET https://help.aliyun.com/document_detail/73478.html" 206 0 49369 49369 "-" "huawei" - HIT - - 0_0_0 002 - - - -
10.24.7.16 [24/Jul/2018:00:00:00 +0800] - "GET https://help.aliyun.com/document_detail/73479.html" 206 0 83821 83821 "-" "vivo" - HIT - - 0_0_0 003 - - - -
为使数据单列上传,首先在MaxCompute项目空间内创建一个单列的表格用于接收数据:odps@ bigdata_DOC>create table userlog1(data string);
使用一个不存在的列分隔符 "u0000"上传数据,从而达到不分割列的效果:odps@ bigdata_DOC>tunnel upload C:\userlog.txt userlog1 -s false -fd "\u0000" -rd "\n";
完成原始数据上传后,使用MaxCompute IntelliJ IDEA编写一个Python UDF(您也可以使用JAVA UDF,注意使用Python UDF需提交工单申请权限),详情可参见Python开发使用须知。
使用代码如下:
from odps.udf import annotate
from odps.udf import BaseUDTF
import re #此处引入正则函数
regex = '([(\d\.)]+) \[(.*?)\] - "(.*?)" (\d+) (\d+) (\d+) (\d+) "-" "(.*?)" - (.*?) - - (.*?) (.*?) - - - -' #使用的正则表达式
# line -> ip,date,request,code,c1,c2,c3,ua,q1,q2,q3
@annotate('string -> string,string,string,string,string,string,string,string,string,string,string') #请注意string数量和真实数据保持一致,本例中有11列。
class ParseAccessLog(BaseUDTF):
def process(self, line):
try:
t = re.match(regex, line).groups()
self.forward(t[0], t[1], t[2], t[3], t[4], t[5], t[6], t[7], t[8], t[9], t[10])
except:
pass
完成函数的编写后,选择上传代码。
上传时请注意选择当前使用的项目。
完成上传后,注册函数并填写函数名称,本例中函数名称为ParseAccessLog。
函数上传完成后,就可以使用编写的UDF函数处理上传到表格userlog1的原始数据了,注意不要写错列的名称,本例中为data。您可以使用正常的SQL语法,新建一个表格userlog2用于存放处理后的数据。odps@ bigdata_DOC>create table userlog2 as select ParseAccessLog(data) as (ip,date,request,code,c1,c2,c3,ua,q1,q2,q3) from userlog1;
完成处理后,可以观察到目标表已创建,数据成功分列。
+----+------+---------+------+----+----+----+----+----+----+----+
| ip | date | request | code | c1 | c2 | c3 | ua | q1 | q2 | q3 |
+----+------+---------+------+----+----+----+----+----+----+----+
| 10.21.17.2 | 24/Jul/2018:00:00:00 +0800 | GET https://help.aliyun.com/document_detail/73477.html | 200 | 0 | 81615 | 81615 | iphone | HIT | 0_0_0 | 001 |
| 10.17.5.23 | 24/Jul/2018:00:00:00 +0800 | GET https://help.aliyun.com/document_detail/73478.html | 206 | 0 | 4936 | 4936 | huawei | HIT | 0_0_0 | 002 |
| 10.24.7.16 | 24/Jul/2018:00:00:00 +0800 | GET https://help.aliyun.com/document_detail/73479.html | 206 | 0 | 83821 | 83821 | vivo | HIT | 0_0_0 | 003 |
+----+------+---------+------+----+----+----+----+----+----+----+
Q:MaxCompute使用Tunnel Upload命令上传数据,如何实现批量上传一个目录下的多个文件到同一张表,并且每个文件放在不同的分区内?
A:可以巧妙的利用Shell脚本实现上述功能,本章节中以在Windows环境下配合odpscmd客户端使用Shell脚本举例,Linux环境下原理相同。
Shell脚本内容如下。
#!/bin/sh
C:/odpscmd_public/bin/odpscmd.bat -e "create table user(data string) partitioned by (dt int);" //首先创建一个分区表user,分区关键字为dt,本例中odpscmd客户端的安装路径为C:/odpscmd_public/bin/odpscmd.bat,您可以根据您的实际环境调整路径。
dir=$(ls C:/userlog) //定义变量dir,为存放文件的文件夹下所有文件的名称
pt=0 //变量pt用于作为分区值,初始为0,每上传好一个文件+1,从而实现每个文件都存放在不同的分区
for i in $dir //定义循环,遍历文件夹C:/userlog下的所有文件
do
let pt=pt+1 //每次循环结束,变量pt+1
echo $i //显示文件名称
echo $pt //显示分区名称
C:/odpscmd_public/bin/odpscmd.bat -e "alter table user add partition (dt=$pt);tunnel upload C:/userlog/$i user/dt=$pt -s false -fd "%" -rd "@";" //利用odpscmd首先添加分区,然后向分区中上传文件
done
实际运行shell脚本效果如下,本例中以两个文件userlog1及userlog2举例。
完成上传后,您可以在odpscmd客户端查看表数据。
网络问题
Q:MaxCompute使用Tunnel Upload命令上传数据时为什么报错java.io.IOException: Error writing request body to server
?
A:这是一个上传数据到服务器的时的异常,通常是因为上传过程中的网络链接断开/超时导致的:
- 可能是用户的数据源并非是来自本地文件,而是需要从诸如数据库等一类的地方获取,导致数据在写入的过程中还需要等待数据获取导致的超时。目前UploadSession在上传数据的过程中,如果600秒没有数据上传,则被认为超时。
- 用户通过公网的Endpoint来做数据上传,由于公网网络质量不稳定导致超时。
解决方法:
- 在上传的过程中,先把获取数据,再调用Tunnel SDK上传数据。
- 一个block可以上传64M-1G的数据,最好不要超过1万条数据以免带来重试的时间导致的超时。一个Session可以挂最多2万个block。
如果用户的数据是在ECS上,可以参考访问域名和数据中心配置合适的Endpoint,可以提速并节省费用。
Q:MaxCompute使用Tunnel Upload命令行上传数据,设置了经典网络的Endpoint,但为什么会连接到外网的Tunnel Endpoint?
A:配置文件odps_config.ini里除了endpoint之外还需要配置tunnel_endpoint。请参考访问域名和数据中心进行配置。目前只有上海region不需要设置tunnel endpoint
Q:MaxCompute使用Tunnel Upload命令行上传数据是否支持限速?上传速率太快的话可能会占用服务器过多的I/O性能。
A:目前MaxCompute使用Tunne lUpload命令行不支持限速,需要通过SDK单独处理。
计费问题
Q:MaxCompute使用Tunnel Upload命令行上传数据计费的带宽,是按照数据压缩前还是压缩后的大小计费?
A:按照Tunnel压缩后的带宽进行计费。