将Hive查询推送到数据库级别

时间:2018-04-10 17:02:15

标签: sql database apache-spark hive

我有100万条记录的表格数据,每条记录有15列。 我需要查询这些数据的3列,并过滤掉用于进一步处理的记录。

目前,我正在两种方法之间做出决定

方法1 将数据存储为HDFS中的csv或镶木地板。当我需要查询使用Spark SQL读取整个数据和查询时。

方法2 使用HiveContext创建Hive表并保留表和Hive元数据。使用HiveContext在需要时查询此表。

疑惑:

  1. 在方法2中,查询是否被推送到数据库级别(HDFS),只读取并返回满足条件的记录?或者将整个数据读入内存(与大多数spark作业一样),然后使用元数据运行查询?
  2. 运行时:这两种方法中哪一种会更快?
  3. 请注意,Hive设置不是Hive over Spark,它是随Spark提供的HiveContext。

    Spark版本:2.2.0

2 个答案:

答案 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的值,甚至忽略表中的其他列。