内容
1.SparkSQL下的Parquet使用最佳实践
2.SparkSQL下的Parquet实战
一、SparkSQL下的Parquet使用最佳实践
1.过去整个业界对大数据的分析的技术栈的pipeline一般分为两种方式:
a)Data Source->HDFS->MR/Hive/Spark(相当于ETL)->HDFS Parquet->SparkSQL/Impala->Result Service(可以放在DB中,也有可能被通过JDBC/ODBC来作为数据服务使用);
b)Data Source->Real Time update data to HBase/DB->Export to Parquet->SparkSQL/Impala->esult Service(可以放在DB中,也有可能被通过JDBC/ODBC来作为数据服务使用);
上述的第二种方式完全可以通过Kafka+SparkStreaming+SparkSQL(内部也强烈建议采用Parquet的方式来存储数据)的方式取代;
使用Hive主要原因:Hive曾经与数据;
2.期待的方式:Data Source->Kafka->SparkStreaming->Parquet->SparkSQL(ML/GraphX...)->Parquet->其他各种Data Mining等;
二、Parquet的精要介绍
1.Parquet是列式存储格式的一种文件类型,列式存储有以下的核心优势:
a)可以跳过不符合条件的数据,制度取需要的数据,降低IO数据量;
b)压缩编码可以降低磁盘存储空间。由于同一列的数据类型是一样的,可以使用更高效的压缩编码(例如Run Length Encoding 和Delta Encoding)进一步节约存储空间;
c)只读取需要的列,支持向量运算,能够获取更好的扫描性能;
三、代码实例
1.直接输出查询结果
package SparkSQL;
import org.apache.spark.SparkConf;
import org.apache.spark.api.java.JavaSparkContext;
import org.apache.spark.sql.Dataset;
import org.apache.spark.sql.Row;
import org.apache.spark.sql.SQLContext;
import java.util.List;
/**
* FileName: SparkSQLParquetOps
* Author: hadoop
* Email: 3165845957@qq.com
* Date: 18-10-31 下午11:10
* Description:
*/
public class SparkSQLParquetOps {
public static void main(String[] args){
//创建SparkConf用于读取系统信息并设置运用程序的名称
SparkConf conf = new SparkConf().setAppName("DataFrameOps").setMaster("spark://Master:7077");
//创建JavaSparkContext对象实例作为整个Driver的核心基石
JavaSparkContext sc = new JavaSparkContext(conf);
//设置输出log的等级
sc.setLogLevel("INFO");
//创建SQLContext上下文对象,用于SqL的分析
SQLContext sqlContext = new SQLContext(sc);
Dataset userDS =sqlContext.read().parquet("/usr/local/spark/examples/src/main/resources/users.parquet");
userDS.registerTempTable("users");
Dataset result = sqlContext.sql("select * from users");
List<Row> listRow = result.javaRDD().collect();
for (Row row:listRow){
System.out.println(row);
}
}
}
运行结果:
修改查询条件后:
Dataset result = sqlContext.sql("select name from users");
结果:
2.将查询结果转化为?RDD输出
package SparkSQL;
import org.apache.spark.SparkConf;
import org.apache.spark.api.java.JavaRDD;
import org.apache.spark.api.java.JavaSparkContext;
import org.apache.spark.api.java.function.Function;
import org.apache.spark.sql.Dataset;
import org.apache.spark.sql.Row;
import org.apache.spark.sql.SQLContext;
import java.util.List;
/**
* FileName: SparkSQLParquetOps
* Author: hadoop
* Email: 3165845957@qq.com
* Date: 18-10-31 下午11:10
* Description:
*/
public class SparkSQLParquetOps {
public static void main(String[] args){
//创建SparkConf用于读取系统信息并设置运用程序的名称
SparkConf conf = new SparkConf().setAppName("DataFrameOps").setMaster("local");
//创建JavaSparkContext对象实例作为整个Driver的核心基石
JavaSparkContext sc = new JavaSparkContext(conf);
//设置输出log的等级
sc.setLogLevel("INFO");
//创建SQLContext上下文对象,用于SqL的分析
SQLContext sqlContext = new SQLContext(sc);
Dataset userDS =sqlContext.read().parquet("/usr/local/spark/examples/src/main/resources/users.parquet");
userDS.registerTempTable("users");
Dataset result = sqlContext.sql("select name from users");
JavaRDD<String> resultRDD = result.javaRDD().map(new Function<Row, String>() {
@Override
public String call(Row row) throws Exception {
return "This name is :"+row.getAs("name");
}
});
List<String> listRow = resultRDD.collect();
for (String row:listRow){
System.out.println(row);
}
}
}
结果: