【问题标题】:Difference between df.SaveAsTable and spark.sql(Create table..)df.SaveAsTable 和 spark.sql 之间的区别(创建表..)
【发布时间】:2019-09-05 15:50:57
【问题描述】:

saveastable和insertInto的区别参考here

以下两种方法有什么区别:

df.saveAsTable("mytable");

df.createOrReplaceTempView("my_temp_table");
spark.sql("drop table if exists " + my_temp_table);
spark.sql("create table mytable as select * from 
my_temp_table");

在哪种情况下表存储在内存中,在哪种情况下物理存储在磁盘上?

另外,根据我的理解,createOrReplaceTempView 仅注册数据帧(已经在内存中)以通过 Hive 查询访问,而不实际持久化,对吗?

我必须加入数百个表并遇到 OutOfMemory 问题。 就效率而言,最好的方法是什么?

  • df.persist() 和 df.join(..).join(..).join(..)....#hundred 连接

  • createOrReplaceTempView 然后加入spark.sql()

  • SaveAsTable(?不确定下一步)

  • 使用Create Table 写入磁盘,然后使用spark.sql() 加入?

【问题讨论】:

    标签: scala apache-spark hive pyspark apache-spark-sql


    【解决方案1】:

    让我们一步一步来。

    df.saveAsTable("mytable") 的情况下,表实际上是写入存储(HDFS/S3)。这是一个 Spark 动作。

    另一方面: df.createOrReplaceTempView("my_temp_table") 是一种转换。它只是用于df 的 DAG 的标识符。实际上没有任何东西存储在内存或磁盘中。

    spark.sql("drop table if exists " + my_temp_table) 放下桌子。

    spark.sql("create table mytable as select * from my_temp_table") 在存储上创建 mytablecreateOrReplaceTempViewglobal_temp 数据库中创建表。

    最好将查询修改为:

    create table mytable as select * from global_temp.my_temp_table

    createOrReplaceTempView 只注册数据框(已经在 memory) 可通过 Hive 查询访问,实际上无需 坚持下去,对吗?

    是的,对于大型 DAG,spark 将根据 spark.memory.fraction 设置自动缓存数据。查看this页面。

    我必须加入数百个表并遇到 OutOfMemory 问题。在条款 效率,什么是最好的方法?

    df.persist() and df.join(..).join(..).join(..).... #hundred joins
    
    createOrReplaceTempView then join with spark.sql(),
    
    SaveAsTable (? not sure the next step)
    
    Write to disk with Create Table then join with spark.sql()?
    

    persist 会根据可用内存以缓存格式存储一些数据,对于通过连接数百个表生成的最终表,这可能不是最好的方法。

    无法推荐适合您的方法,但这里有一些通用模式:

    如果写入失败并出现 OOM 并且使用默认的 spark.shuffle.partitions,则开始点是增加 shuffle 分区计数,以确保每个执行程序的分区大小根据其内存可用性正确调整。

    spark.shuffle.partitions 设置可以在不同的连接中设置,它不需要是整个 Spark 作业的常量。

    如果涉及多个表,计算分区大小会变得很困难。在这种情况下,在大表之前写入磁盘并回读是个好主意。

    对于小于 2GB 的小型表,可以进行广播。默认限制是 10MB(我认为),但可以更改。

    最好将最终表存储在磁盘上,而不是通过临时表为 thrift 客户端提供服务。

    祝你好运!

    【讨论】:

    • 感谢您的洞察,Sai。您的意思是 SaveAsTableCreate Table 是相同的,都写入 HDFS 吗?我遇到的问题更好地描述了 stackoverflow.com/questions/55656759/… 。这是典型的特征处理,一个特征生成 5-10 列的小表,最后将它们全部连接起来。我在 OutOfMemory 之前的限制是 500k 行,200 个特征(产生 500 多个列)。我试过都分成块:(join20)join(join20)和从左到右((join20)join20)
    • @Kenny, Do you mean that SaveAsTable and Create Table are the same, both writing to HDFS ? 是的。 I tried both splitting into chunks: (join20)join(join20) and left to right ((join20)join20) 这行不通,因为连接只是转换,火花计划会压平所有连接,无论如何它们都被破坏了。我想拆分连接的想法是减少 DAG(?),在这种情况下,您可能希望在尝试更大的表连接之前保存连接的表。
    • 例如:A join B = C, C join D = E 假设 E 是您感兴趣的表,D 是一个大表(因为会发生 OOM)。当像 saveAsTable 这样的 Spark 操作时,或者如果您将其注册为临时表并通过 Thrift 查询它,则计划将是 A join B join D,这意味着 DAG 不会缩短。但是如果 C 通过写入磁盘来保存(因为它是一个动作),那么下一个连接将真正是 C join D
    猜你喜欢
    • 2012-11-30
    • 1970-01-01
    • 2022-10-04
    • 1970-01-01
    • 2021-11-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-03
    相关资源
    最近更新 更多