【问题标题】:PySpark - Hive Context Does Not Return Results but SQL Context Does for Similar QueryPySpark - Hive 上下文不返回结果,但 SQL 上下文返回类似查询
【发布时间】:2016-01-13 02:16:13
【问题描述】:

当我在 PySpark 中运行 HiveContext 与 SQLContext 进行可比查询时,我注意到性能存在巨大差异

版本/配置

  • Spark 1.3.1(也试过 Spark 1.5.1
  • Hadoop 2.6(在 CDH 5.4.0 上)
  • pyspark --master yarn --num-executors 5 --executor-memory 10g --driver-memory 4g --driver-cores 4

表格信息

  • database.table 有超过 2k 个分区
  • database.table 在 field1 上分区(在 where 子句中使用)

HIVECContext 实现

from pyspark.sql import SQLContext
sqlContext = HiveContext(sc) 
qry = "select count(*) from database.table a where a.field1 = 'ABCD'"
results = sqlContext.sql(qry).collect()
  • 花费不确定的时间 - 我不得不停止执行查询,因为它很快占用了我执行查询的边缘节点上超过 50% 的系统资源。

SQLCONTEXT 实现

from pyspark.sql import SQLContext
sqlContext = SQLContext(sc)
df = sqlContext.parquetFile('hdfs_path_to_hive_table/field1=ABCD/')
df.select("field2").show()
  • 执行需要 6.5 秒并按预期返回数据帧。

问题

  • 有没有人注意到类似的事情?
  • 后端发生了什么可能导致这种资源消耗,我可以做些什么来避免它?

任何帮助将不胜感激!

2015 年 10 月 16 日更新

我试过了:

SET spark.sql.hive.metastorePartitionPruning=true

我仍然遇到同样的问题。我让进程运行了一段时间,以测试 CPU 使用率会上升到多高,达到 2000% 以上!

我听说 parquet 格式的文件在 1.5 版之前可能是 spark 的问题,所以我在 spark 1.5.1 中使用这些额外设置进行了所有测试:

parquet.task.side.metadata=false
SET spark.sql.parquet.filterPushdown=true
SET spark.sql.parquet.cacheMetadata=false

但他们似乎都没有帮助。

在我寻求答案的过程中,我遇到了这些不同的链接,这些链接让我尝试了上述配置:

  • Spark 读取 Parquet 的元存储(parquet.task.side.metadata=false 和 SET spark.sql.parquet.filterPushdown=true):
    • _https://issues.apache.org/jira/browse/SPARK-5346
    • _http://stackoverflow.com/questions/31226757/partitions-not-being-pruned-in-simple-sparksql-queries
  • Spark 1.5.1 配置链接(SET spark.sql.parquet.cacheMetadata=false):
    • _http://spark.apache.org/docs/latest/sql-programming-guide.html#configuration
  • 链接到与我的非常相似的上一个问题
    • _https://mail-archives.apache.org/mod_mbox/spark-user/201509.mbox/%3CCAAswR-7C0Cfduj+iaVDb-XvrnCHScrh34Lo0BadWH6XPzUXePA@mail.gmail.com%3E李>

【问题讨论】:

    标签: python hadoop apache-spark pyspark


    【解决方案1】:

    collect() ---> 将所有数据获取到边缘节点
    show() ---> 将显示几个样本点,前 20 个数据积分

    当数据量很大时,显然你会看到时间和内存的巨大差异。

    【讨论】:

      【解决方案2】:

      .collect() 和 .show() 非常不同

      您看到的性能差异可能是由于 collect(将整个结果数据帧拉入驱动程序)和 show(默认情况下仅显示结果数据帧的前 20 行)之间的差异。

      您似乎没有在血统中进行任何改组操作,因此可能是该节目仅拉入 20 行(而不是整个数据集,如 .collect() 案例)

      【讨论】:

      • 是的,这是真的。但我仍然看到 HiveContext 和 SQLContext 之间的性能问题以及相同的查询。
      【解决方案3】:

      这可能不是 HiveContext/SQLContext 之间的差异,而是元数据来自 HiveMetastore 的表与 SparkSQL 数据源 API 之间的差异。我猜如果您以相同的方式创建表,性能会相似。

      在数据源 API 中,我们花费了大量时间来优化许多分区的发现和处理,总的来说,我会说这条路径更容易使用/更快。

      hive 表的问题可能是从元存储下载所有分区元数据并将其转换为我们的内部格式。我们对所有分区都这样做,即使在这种情况下您只需要前 20 行。

      为了在这种情况下提高性能,我会尝试运行:

      SET spark.sql.hive.metastorePartitionPruning=true

      【讨论】:

      • 谢谢我尝试使用:SET spark.sql.hive.metastorePartitionPruning=true 但它似乎不起作用(见上面的更新部分)。我的一位同事尝试了 API,但他说他也遇到了同样的问题。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-05-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-04-11
      相关资源
      最近更新 更多