Apache spark ApacheSpark:重新分区、排序和缓存对连接的影响

Apache spark ApacheSpark:重新分区、排序和缓存对连接的影响,apache-spark,pyspark,bigdata,azure-databricks,delta-lake,Apache Spark,Pyspark,Bigdata,Azure Databricks,Delta Lake,我正在探索Spark在加入一张桌子时的行为。我正在使用数据记录器 我的虚拟场景是: 将外部表作为数据帧A读取(底层文件为增量格式) 将dataframe B定义为dataframe A,仅选择某些列 连接第1列和第2列上的数据帧A和B (是的,这没有多大意义,我只是在尝试了解Spark的基本机制) 我的第一次尝试是按原样运行代码(尝试1)。然后我尝试重新分区和缓存(尝试2) 最后,我重新分区、排序和缓存 a = spark.read.table("table") \ .select("colu

我正在探索Spark在加入一张桌子时的行为。我正在使用数据记录器

我的虚拟场景是:

  • 将外部表作为数据帧A读取(底层文件为增量格式)

  • 将dataframe B定义为dataframe A,仅选择某些列

  • 连接第1列和第2列上的数据帧A和B

  • (是的,这没有多大意义,我只是在尝试了解Spark的基本机制)

    我的第一次尝试是按原样运行代码(尝试1)。然后我尝试重新分区和缓存(尝试2)

    最后,我重新分区、排序和缓存

     a = spark.read.table("table") \
    .select("column1", "column2", "column3", "column4") \
    .withColumn("columnA", lower((concat(col("column4"), lit("_"), col("column5")))))
    .repartition(col("column1"), col("column2")).sortWithinPartitions(col("column1"), col("column2")).cache()
    
    生成的各个DAG如附件所示

    我的问题是:

  • 为什么在尝试1中,即使未明确指定缓存,表仍显示为缓存

  • 为什么InMemoreTableScan后面总是跟有此类型的另一个节点

  • 为什么尝试3中的缓存出现在两个阶段上

  • 为什么在尝试3时,在MemoreTableScan中只跟随一个(且只有一个)


  • 您在这三个计划中看到的是DataBricks runtime和Spark的混合

    首先,在运行DataBricks runtime 3.3+时,会自动为所有拼花文件启用缓存。 相应的配置:
    spark.databricks.io.cache.enabled true

    对于第二个查询,InMemoryTableScan发生了两次,因为就在调用join时,spark尝试并行计算数据集A和数据集B。假设为不同的执行者分配了上述任务,这两个执行者都必须从(DataBricks)缓存中扫描表

    对于第三个,InMemoryTableScan本身并不涉及缓存。这只意味着catalyst形成的任何计划都涉及多次扫描缓存表


    PS:我无法想象第4点:)

    我怀疑当数据源是外部表时,DataFrame reader会自动缓存数据。我有类似的情况,我正在从数据库表读取数据,而正在下载“应用程序详细信息UI”上的“SQL”选项卡显示正在下载的行数,但尚未在指定位置保存任何文件。我猜它知道计数,因为它在某处缓存了数据,而这就是DAG上显示的数据。如果在本地从文本文件读取数据,则不会看到缓存状态。
    a = spark.read.table("table") \
    .select("column1", "column2", "column3", "column4") \
    .withColumn("columnA", lower((concat(col("column4"), lit("_"), col("column5")))))
    .repartition(col("column1"), col("column2")).cache()
    
     a = spark.read.table("table") \
    .select("column1", "column2", "column3", "column4") \
    .withColumn("columnA", lower((concat(col("column4"), lit("_"), col("column5")))))
    .repartition(col("column1"), col("column2")).sortWithinPartitions(col("column1"), col("column2")).cache()