spark(七):DataSet

说明

本博客周五更新 本文记录spark 分布式数据类型DataSet的基本原理和使用方法。 DataSet是Spark1.6添加的分布式数据集合,Spark2.0合并DataSet和DataFrame数据集合API,DataFrame变成DataSet的子集。 DataSet继承RDD优点,并使用Spark SQL优化的执行引擎。支持JVM对象构建,支持函数式转换(map/flatmap/filter)等多种操作

资料

优势

  • 静态类型和运行时类型检查,编译时检查类型,避免程序运行中因类型错误造成任务失败。
  • High-level抽象以及结构化半结构化数据集的自定义视图
    • DataFrame是Dataset[Row]的集合,把结构化数据集视图转换成半结构化数据集。例如,有个海量IoT设备事件数据集,用JSON格式表示。JSON是一个半结构化数据格式,很适合使用Dataset, 转成强类型的Dataset[DeviceIoTData]。
  • 简单易用的API
    • 结构化数据给spark程序操作数据集带来很多限制,同时也引入了丰富的语义和易用的特定领域语言,如filter()、map()等。
  • 性能和优化
    • 因为Spark DataFrame和DataSet构建于Spark SQL引擎纸上,它会使用Catalys优化器生成优化的逻辑计划和物理查询计划任务,以带来空间和速度上的提升。

代码实例

  • java版DataSet方式操作数据,测试数据为|分隔,共6个字段:date、name、condition、city、platform、version,类型string。
public class WordPro {
	private static SparkSession gloableSpark;
	private static Logger logger = LoggerFactory.getLogger(WordPro.class);
 
	public static void main(String[] args) {
		//获取sparkSession
		SparkSession spark = SparkSession.builder().appName("wordPro").master("local[4]").getOrCreate();
		gloableSpark = spark;
		JavaRDD<Row> rowRDD = spark.read().text("D:\\data\\sparksql\\pro\\keyword.txt").toJavaRDD();
		logger.info("完整数据:");
		rowRDD.collect().forEach(line -> System.out.println(line));
 
		//将长度不符合规范的数据先过滤掉
		JavaRDD<Row> programRdd = rowRDD.filter(new Function<Row, Boolean>() {
			private static final long serialVersionUID = 975739302260154160L;
 
			@Override
			public Boolean call(Row v1) throws Exception {
				boolean result = v1.get(0).toString().split("\\|").length == 6;
				return result;
			}
		}).map(new Function<Row, Row>() {
			//将数据根据tab进行拆分重组成为符合StructType的JavaRdd<Row>
			@Override
			public Row call(Row v1) throws Exception {
				String[] datas = v1.get(0).toString().split("\\|");
				Row row = RowFactory.create(
						datas[0],
						datas[1],
						datas[2],
						datas[3],
						datas[4],
						datas[5]
				);
				return row;
			}
		});
		//根据StructField来创建StructType
		List<StructField> structFieldList = new ArrayList<>();
		structFieldList.add(DataTypes.createStructField("date", DataTypes.StringType, true));
		structFieldList.add(DataTypes.createStructField("name", DataTypes.StringType, true));
		structFieldList.add(DataTypes.createStructField("condition", DataTypes.StringType, true));
		structFieldList.add(DataTypes.createStructField("city", DataTypes.StringType, true));
		structFieldList.add(DataTypes.createStructField("platform", DataTypes.StringType, true));
		structFieldList.add(DataTypes.createStructField("version", DataTypes.StringType, true));
		StructType structType = DataTypes.createStructType(structFieldList);
		//通过structType将rdd转换为Dataset
		Dataset<Row> infoDataset = spark.createDataFrame(programRdd, structType);
		//创建临时表
		infoDataset.createOrReplaceTempView("info");
		//构造查询条件
		Map<String, String> params = new HashMap<>(2);
		params.put("city", "nanjing");
		selectByCondition(params);
	}
 
	private static void selectByCondition(Map<String, String> params) {
		String city = params.get("city");
		String platform = params.get("platform");
		//拼接查询sql
		StringBuffer sqlBuffer = new StringBuffer("select * from info where 1=1 ");
		sqlBuffer = city == null ? sqlBuffer : sqlBuffer.append(" and city = '" + city + "'");
		sqlBuffer = platform == null ? sqlBuffer : sqlBuffer.append(" and platform = '" + platform + "'");
		String sql = sqlBuffer.toString();
		logger.info("查询sql:" + sql);
		gloableSpark.sql(sql).show();
	}
}

DataFrame和DataSet的区别

  • DataFrame 一行记录中没有指定特定的数据类型
  • Dataset 一行记录中每个对象有明确类型

总结

  • DataSet在DataFrame基础上支持更强的数据类型控制,更精细化操作数据,避免因数据类型异常,造成的程序运行异常。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章