第66课:SparkSQL下Parquet中PushDown的实现学习笔记

本文深入探讨了SparkSQL在处理Parquet文件时的PushDown优化技术,解释了PushDown如何减少数据输入并提高处理效率。通过分析SparkSQL的QueryExecution流程和optimizer的优化策略,如Filter的合并与位置调整,展示了PushDown在执行计划中的作用。接着,文章详细讲解了PushDown在Parquet中的具体实现,包括RowGroupFilter和Record Filter两个层面,揭示了Parquet如何利用统计信息和数据结构来过滤数据。最后,讨论了在Parquet文件中如何利用这些优化策略来提高查询性能。
摘要由CSDN通过智能技术生成

66课:SparkSQLParquetPushDown的实现学习笔记

本期内容:

1  SparkSQL下的PushDown的价值

2  SparkSQL下的ParquetPuahDown实现

 

Hive中也有PushDownPushDown可以极大减少数据输入,极大的提高处理效率。

SparkSQL实现了PushDown,在Parquet文件中实现PushDown具有很重要的意义。

PushDown是一种SQL优化方式,通常用在查询。应用场景:

假设通过DataFramedf.select(a,b,c).filter(by a).filter(by b).select(c).filter(by c)这样的查询,在optimizer阶段,需要合并多个filters(CombineFilters),并调整算子间的顺序,例如将部分filter移到select等前面(PushPredicateThroughAggregate/Generate/Join/Project)filter前需要操作一大批数据,但filter后只需要操作很小一部分数据,SQL优化时就希望一开始就只操作这一小部分数据,而不需要把所有数据都导入进来,因为最终还是要被过滤掉。

PushDown本身既有SQL语法的层面也有物理执行的层面。

语法层面,SparkSQLHive都有自己的语法实现。

下面看一下QueryExecution的源码:

/**
 * The primary workflow for executing relational queries using Spark.  Designed to allow easy
 * access to the intermediate phases of query execution for developers.
 *
 * While this is not a public class, we should avoid changing the function names for the sake of
 * changing them, because a lot of developers use the feature for debugging.
 */
class QueryExecution(valsqlContext: SQLContext, vallogical: LogicalPlan) {

  def assertAnalyzed(): Unit = sqlContext.analyzer.checkAnalysis(analyzed)

  lazy val analyzed: LogicalPlan = sqlContext.analyzer.execute(logical)

  lazy val withCachedData: LogicalPlan = {
    assertAnalyzed()
    sqlContext.cacheManager.useCachedData(analyzed)
  }

  lazy val optimizedPlan: LogicalPlan = sqlContext.optimizer.execute(withCachedData)

  lazy val sparkPlan: SparkPlan = {
    SQLContext.setActive(sqlContext)
    sqlContext.planner.plan(optimizedPlan).next()
  }

  // executedPlan should not be used to initialize any SparkPlan. It should be
  // only used for execution.
  
lazy valexecutedPlan: SparkPlan = sqlContext.prepareForExecution.execute(sparkPlan)

  /** Internal version of the RDD. Avoids copies and has no schema */
  
lazy valtoRdd: RDD[InternalRow] =executedPlan.execute()

  protected def stringOrError[A](f: =>A): String =
    try f.toString catch { casee: Throwable => e.toString }

  def simpleString: String = {
    s"""== Physical Plan ==
       |$
{stringOrError(executedPlan)}
      """.stripMargin.trim
  }

  override def toString:String = {
    def output =
      analyzed.output.map(o =>s"${o.name}:${o.dataType.simpleString}").mkString(", ")

    s"""== Parsed Logical Plan ==
       |$
{stringOrError(logical)}
       |== Analyzed Logical Plan ==
       |$
{stringOrError(output)}
       |$
{stringOrError(analyzed)}
       |== Optimized Logical Plan ==
       |$
{stringOrError(optimizedPlan)}
       |== Physical Plan ==
       |$
{stringOrError(executedPlan)}
    """.stripMargin.trim
  }
}

QueryExecution在具体实现时会把工作过程串联成一个WorkFlow

SQL语句的翻译过程:

1 基本语法翻译

2 pharser翻译

3 优化

4 Logical plan

5 Physical执行计划

6 引擎上执行

例如DataFramedf.select(a,b,c).filter(by a).filter(by b).select(c).filter(by c)这样一个SQL语句,在执行前会生成一个语法树,解析和优化,在优化阶段会把Filter合并,在合并时会考虑Filter的顺序。

下面再看一下spark.sql.catalyst的Optimizer的源码:

package org.apache.spark.sql.catalyst.optimizer

abstract class Optimizerextends RuleExecutor[LogicalPlan]

object DefaultOptimizer extends Optimizer {
  val batches=
    // SubQueries are only needed for analysis and can be removed before execution.
    Batch
("Remove SubQueries",FixedPoint(100),
      EliminateSubQueries) ::
    Batch("Aggregate",FixedPoint(100),
      ReplaceDistinctWithAggregate,
      RemoveLiteralFromGroupExpressions) ::
    Batch("Operator Optimizations",FixedPoint(100),
      // Operator push down
      
SetOperationPushDown,
      SamplePushDown,
      PushPredicateThroughJoin,
      PushPredicateThroughProject,
      PushPredicateThroughGenerate,
      PushPredicateThroughAggregate,
      ColumnPruning,
      // Operator combine
      
ProjectCollapsing,
      CombineFilters,
      CombineLimits,
      // Constant folding
      
NullPropagation,
      OptimizeIn,
      ConstantFolding,
      LikeSimplification,
      BooleanSimplification,
      RemoveDispensableExpressions,
      SimplifyFilters,
      Simpli

Pushdown Join是一种优化关系型数据库查询的技术,其主要思想是将Join操作下推到数据源执行,以减少数据传输和处理的次数,提高查询效率。在Pushdown Join,数据源可以是关系型数据库表、文件、缓存等,查询计划可以是SQL、MapReduce等。 Pushdown Join可以通过以下步骤实现: 1. 识别Join操作:在查询计划识别Join操作,并确定Join的条件和Join的表。 2. 下推Join操作:将Join操作下推到数据源执行,这意味着Join操作将在数据源执行,而不是在查询计划执行。 3. 执行Join操作:在数据源执行Join操作,返回Join的结果。 4. 将Join结果返回到查询计划:将Join的结果返回到查询计划,以便在查询计划进行后续的操作。 Pushdown Join的优点包括: 1. 减少数据传输:Pushdown Join可以在数据源执行Join操作,减少数据传输的次数,从而提高查询效率。 2. 利用数据源的优化能力:Pushdown Join可以利用数据源的优化能力,如索引、分区等,提高查询效率。 3. 提前过滤数据:Pushdown Join可以在数据源提前过滤出不必要的数据,减少数据传输的量,从而提高查询效率。 Pushdown Join的缺点包括: 1. 数据源的负担增加:Pushdown Join将Join操作下推到数据源执行,可能会增加数据源的负担。 2. 复杂性增加:Pushdown Join需要在查询计划识别Join操作,并将Join操作下推到数据源执行,这增加了查询计划的复杂性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值