1

简介

当人们把越来越多的大数据存储在HDFS或者AWS的S3上,通常下一个问题是如何让全公司范围的员工能够方便的查询这些数据。一个选项是建立一个SQL-on-Hadoop系统,让用户使用SQL或者类SQL语言来查询数据,但是这些SQL-on-Hadoop系统往往比较复杂,需要一定的开发和维护工作量。

另一个选项是,如果你已经有了Spark或者Hadoop YARN集群,那么利用Spark SQL,通过编写少量的代码,你就可以建立一个轻量级的工具,让用户自己提交SQL语句,来获取他们需要的数据。

主要思路

这里的思路是编写一个Spark程序,在其中设置DataFrame(Spark SQL中的数据表)的数据格式(schema),然后用户可以通过Spark程序的参数,指定一个SQL查询,进而执行这个查询。

示例代码

让我们通过一个具体的例子,来展示如何通过代码实现这样的功能。具体代码参见这里,下面是一些简略解释。

数据文件

我们在AWS S3中有两个文件: "s3n://bopublic/demo/selfservicequery/customers.json" 和 "s3n://bopublic/demo/selfservicequery/orders.json"。

Spark程序

我们编写完Spark程序后,用户可以通过以下命令行执行SQL语句:

java -cp ... YourJob -q "select * from customers join orders on customers.key = orders.customerKey"

创建DataFrame数据格式(schema)

在Spark中,StructType类用来定义DataFrame的数据格式(schema)。下面代码展示如何创建"customers"数据表的schema.

private static StructType createCustomerTableSchema() {
StructField[] fields = new StructField[] {
new StructField("key", DataTypes.IntegerType, true,
Metadata.empty()),
new StructField("name", DataTypes.StringType, true,
Metadata.empty()),
new StructField("address", DataTypes.StringType, true,
Metadata.empty())
};

StructType structType = new StructType(fields);
return structType;
}

在Spark中加载数据

SparkConf conf = new SparkConf().setMaster(master).setAppName(
SparkSqlWithExplicitSchema.class.getSimpleName());

JavaSparkContext sc = new JavaSparkContext(conf);

String customerS3Path = "s3n://bopublic/demo/selfservicequery/customers.json";

JavaRDD customerRDD = sc.textFile(customerS3Path).mapPartitions(new ParseJson(customerTableSchema));

创建SQLContext和DataFrame

SQLContext sqlContext = new SQLContext(sc);

DataFrame customerDF = sqlContext.createDataFrame(customerRDD, createCustomerTableSchema());
customerDF.registerTempTable("customers");

运行SQL

String query = (get SQL query from program arguments);
DataFrame resultDF = sqlContext.sql(query);

输出结果

// SerializeToCsv is a class to convert DataFrame row data to CSV. See full source code for details.

JavaRDD csvRDD = resultDF.toJavaRDD().map(new SerializeToCsv());

一点讨论

显式创建Schema

由于Spark SQL可以自动根据JSON检测出数据格式,也许有人认为我们不需要显式地创建DataFrame Schema。这里我们仍然显式创建schema,有两个原因:

  • JSON文件运行忽略某些属性,当这些属性的值是缺省值的时候。当这种情况发生的时候,Spark SQL检测不出这些被忽略的属性格式。

  • 对于其他数据格式,比如CSV,Spark SQL没法检测出schema,显式创建schema使得我们仍然可以查询这些数据源。

Spark Thrift JDBC/ODBC Server

Spark自带一个Thrift JDBC/ODBC Server,人们可以使用"beeline"工具连接上来执行SQL查询,参考Spark文档

这是方法也值得一试,但是目前Spark Thrift Server还未成熟到可以产品化应用的阶段。


扫描微信二维码联系作者
扫描微信二维码联系作者


BoYang
132 声望9 粉丝

Big Data, SQL on Hadoop