前言
这是我第一次写博客,在工作的这一段时间,几乎每天都会学到新的东西,做为一个普通人,我也深感自身记忆力的 一般,所以想通过博客的方式将自己在平时工作中遇到的技术点记录下来,积累的同时也能进行分享。
问题
由于需要从odps表中读取数据,所以我一开始使用的是spark自带DataSource的API方式进行数据读取,具体代码如下:
val df = spark
.read
.format("org.apache.spark.aliyun.odps.datasource")
.option("spark.hadoop.fs.oss.impl", "com.aliyun.fs.oss.nat.NativeOssFileSystem")
.option("odpsUrl", odpsUrl)
.option("tunnelUrl", tunnelUrl)
.option("table", table)
.option("project", project)
.option("accessKeyId", accessKeyId)
.option("accessKeySecret", accessKeySecret)
.load()
可是我发现这样做有个问题,spark读取odps表时,对于有些类型的字段无法正常读取,例如:string,datetime类型都报无法传输的错误,所以我经过考虑后认为可以使用阿里云的maxCompute SDK提供的接口进行读取数据。
依赖
<dependency>
<groupId>com.aliyun.emr</groupId>
<artifactId>emr-core</artifactId>
<version>1.4.3</version>
</dependency>
<dependency>
<groupId>com.aliyun.emr</groupId>
<artifactId>emr-maxcompute_2.11</artifactId>
<version>1.4.3</version>
</dependency>
代码
第一种
使用SQLAPI接口进行数据读取,但这种方式一次只能读取一万条数据,存在局限性。
val account = new AliyunAccount(accessKeyId, accessKeySecret)
val odps = new Odps(account)
odps.setEndpoint(odpsUrl)
odps.setDefaultProject(project)
val instance: Instance = SQLTask.run(odps, "select * from dw_user;")
instance.waitForSuccess()
val resultSet: ResultSet = SQLTask.getResultSet(instance)
while (resultSet.hasNext){
val record: Record = resultSet.next()
if(record.get("register_spm") != null){
println(record.getString("user_id"))
}
第二种
使用tunnel接口进行数据读取
val account = new AliyunAccount(accessKeyId, accessKeySecret)
val odps = new Odps(account)
odps.setEndpoint(odpsUrl)
odps.setDefaultProject(project)
val tunnel = new TableTunnel(odps)
val spec = new PartitionSpec("year_id=2015")
tunnel.setEndpoint(tunnelUrl)
val session: TableTunnel#DownloadSession = tunnel.createDownloadSession(project, table,spec)
val count: Long = session.getRecordCount
println(count)
val tunnelReader: TunnelRecordReader = session.openRecordReader(0,count)
var i = 1
while (i<=count){
val record: Record = tunnelReader.read()
if(record.get("register_spm")!=null){
println(record.getString("register_spm"))
}
i= i+1
}
tunnelReader.close()