我有100万条记录的表格数据,每条记录有15列。 我需要查询这些数据的3列,并过滤掉用于进一步处理的记录。
目前,我正在两种方法之间做出决定
方法1 将数据存储为HDFS中的csv或镶木地板。当我需要查询使用Spark SQL读取整个数据和查询时。
方法2 使用HiveContext创建Hive表并保留表和Hive元数据。使用HiveContext在需要时查询此表。
疑惑:
请注意,Hive设置不是Hive over Spark,它是随Spark提供的HiveContext。
Spark版本:2.2.0
答案 0 :(得分:0)
除非您将第二种方法与可用于优化查询的更高级存储布局(bucketBy
/ DISTRIBUTE BY
)结合起来,否则只要您不这样做,这两者之间就没有区别在方法1中使用模式推断(您必须为DataFrameReader
提供模式。)
Bucketing可用于优化bucketing列上的连接,聚合和过滤器的执行计划,但仍然可以使用Spark执行所有操作。通常,Spark只将Hive用作Metastore,而不是执行引擎。
答案 1 :(得分:0)
在方法2 中,您应该以适当的方式构建和存储配置单元表。 如果hive表被分区并以支持索引的文件格式存储(如ORC),Spark不会加载所有数据。 Spark优化引擎将使用分区修剪和谓词下推,仅加载相关数据以进行进一步处理(转换/操作)。
分区修剪: 选择适当的列(将数据均匀地分布在分区上)以对hive表进行分区。 Spark分区修剪与hive元存储有效地协同工作。它将根据查询的WHERE子句中使用的partition_column仅查看相关分区。
Predicate PushDown: ORC文件具有最小/最大索引和布隆过滤器。也可以在ORC中使用字符串列(不确定最新的镶木地板字符串支持),但在数字列上更有效。 Spark将只读取与筛选器匹配的行,因为它将筛选器推送到底层存储(orc文件)。 下面是一个用于创建此类hive表的示例spark代码段。 (假设raw_df是从原始数据创建的数据框)
sorted_df = raw_df .sort("column2")
sorted_df.write.mode("append").format("orc").partitionBy("column1").saveAsTable("hive_table_name")
这将按照column1值对数据进行分区,以保存hdfs中的orc文件并更新hive Metastore。 使用column2对表进行排序,假设我们将在查询WHERE子句中使用column2。(有效的orc索引需要排序)
然后,您可以查询配置单元并使用相关数据加载spark数据帧。以下是样本。
filtered_df = spark.sql('SELECT column1,column2,column3 FROM hive_table_name WHERE column1= "some_value1" AND column2= "some_value2"')
在上面的示例中,spark将仅查看some_value1分区,因为column1是创建的hive表中的分区列。 然后,Spark将仅在“some_value1”分区下的orc文件中为column2推送谓词(i,e filter)“some_value2”。 这里Spark只加载column1,column2,column3的值,甚至忽略表中的其他列。