版权声明:本文为博主原创文章,遵循 CC 4.0 BY-NC-SA 版权协议,转载请附上原文出处链接和本声明。
ODPS默认都是通过TableTunnel来获取数据,支持分区、续传等。但TableTunnel只支持单表,有时需要联表过滤数据就不能支持了。
官方提供了SQLTask模式来进行一些扩展。
思路
ODPS提供了两种方式来执行SQL:
- 直接使用SQLTask查询数据,但每次不支持超过10000行;
未尝试能否通过多次执行task、每次task限定分页条件实现获取全部数据
- 通过SQLTask创建临时表,通过TableTunnel同步临时表;
推荐第二种方案,实现成本低、可维护性好、性能优秀。
示例代码
最低成本的代码改造思路:
- 创建
com.aliyun.odps.tunnel.TableTunnel
通道,使用其createDownloadSession(String projectName, String tableName)
方法下载表- 该步逻辑与一般通过
TableTunnel
下载单表相同
- 该步逻辑与一般通过
- 调用上述方法时,传入的
tableName
不再是单表名,而是创建的临时表名
private String getRealName() {
String table = generateTempName(), sql = "查询语句";
StringBuilder create = new StringBuilder("CREATE TABLE ").append(table).append(" LIFECYCLE 1 AS ").append(sql);
// SQLTask的sql,要求以;结尾,否则会报错
if (!sql.endsWith(";")) {
create.append(";");
}
Instance i;
try {
// 创建临时表
i = SQLTask.run(odps, create.toString());
i.waitForSuccess();
} catch (OdpsException e) {
throw new RuntimeException("Error to execute odps sql task", e);
}
return table;
}
private String generateTempName() {
// 只支持英文字母、数字、下划线
return new StringBuilder(64).append("temp_task_").append("按自定规则生成的序列号").toString();
}
注意:
- SQL需以
;
结尾,否则报错 - 临时表明只支持英文字母、数字、下划线,否则报错
总结
上面用最快速的方式,在尽可能不侵入原有逻辑的方式下,实现了用SQL同步数据。
但这个方式有个比较大的问题,就是不支持分区,这样跨分区查询数据、大量数据的下载会比较耗时。不过可以在创建临时表、查询SQL中增加分区逻辑,但需要更多开发成本。
参考资料
- https://help.aliyun.com/document_detail/120601.html?spm=a2c4g.11186623.6.973.65b14317QHBhfL
- https://help.aliyun.com/document_detail/73768.html?spm=5176.11065259.1996646101.searchclickresult.69714e9cDvq9mv
以上。感谢您的阅读。