SQL Apacheのスパーク旅行中(中)

では  、「Apacheのスパーク旅行でSQL(上)」  の記事は、我々は、ApacheでのSQL紹介  スパーク  トリップパーサとアナライザ二つのプロセスを、私たちは、接続されているテキストを紹介し続けています。

記事のディレクトリ

最適化ロジック・計画段階 - オプティマイザ

操作取得分析論理計画を変換未解決LogicalPlan関連する前述の論理計画段階の結合、この分析論理プラン直接次いで物理計画に変換することができる  スパーク  実行します。直接はそれを取得した場合でも、実際には、多くの非効率的な文言は、さらに分析論理計画の必要性が、より良い与えるために、効率の問題を作成し、ので、物理的な計画は、おそらくない最適であり得ます論理演算子ツリー。その後、それはオプティマイザオプティマイザSQL論理演算子ツリーのためにされて入ってきました。

この段階では、オプティマイザは、主ルールに基づいて(ルールベース・オプティマイザ、RBOと呼ばれる)、およびルールのほとんどは(除外例えば行作物として勘や経験由来のルールに基づいている発見的規則、あるていますクエリ列を使用する必要はない)、プッシュダウン述語(データソースにできるだけフィルタがシンクに)、そのような1 + 2を計算し、この予め定数として蓄積()とテーブルからのこのようなSELECT *などの一定の置換(ここで、i = 5およびJは= I + 3テー​​ブルからSELECT *に変換することができる。ここで、i = 5、J = 8)などが挙げられます。

そして、以前に同様の結合ロジック計画段階を導入し、この段階で、すべてのルールはルールの抽象クラスを実現することを目的とする、よりRuleExecutorでの実行も、複数のバッチで構成バッチ、バッチを支配、以前のルールを導入されているので実行は、このセクションでは、それらを繰り返すことはしません。

だから、それを実行します。このプロセスの最適化前述のSQL文のために?1つの実行順序ルールにより、ここ1指示に従ってください。

述語プッシュダウン

プッシュダウンスパークSQL述部である  PushDownPredicate 底部、好ましくは、データ・ソースにプッシュダウンされるように、メインフィルタ処理条件を達成しました。次のようにSQLのために、述語プッシュダウン最適化を使用して、我々は計画上述のロジックを取得し、次のとおりです。

SQLスパークの旅で
:あなたは記事のスパーク、HadoopのHBaseのかに関連する、マイクロチャネル公衆番号への歓迎の注意に遅れないようにしたい場合はiteblog_hadoop

図から分かるように、述語プッシュダウンを直接プッシュダウンする前にオペレータを結合フィルタ(図は下から見ていることに注意)。我々はで始まる、すなわち走査T1テーブル((((isnotnull(CID#2)&& isnotnull()は#3 DID)&&(= 1 CID#2))&&(#3 = 2)DID)&&(ID #0> 50000))&& isnotnull(ID#0)データをフィルタリングするフィルタリング基準が条件を満たし、また場合(ID#8)&&(ID#8> 50000)フィルタ基準濾過スキャンテーブルT2 isnotnullで開始しますデータ基準を満たしています。このような操作が完了したら、大幅に計算を高速化するためにオペレータに参加し、処理されたデータの量を減らすことができます。

行作物

スパークSQLの行作物がされて  ColumnPruning 実装されています。テーブル、我々は多くの分野を持っている可能性がありますが、それぞれの時間は、クエリは、我々はすべてのフィールドをスキャンする必要がない可能性が非常に高いことなので、スキャンデータの量が低減されるように、列を使用して、この時間は、不要なフィールドをフィルタリングするためにこれらのクエリをカットすることができます。次のようにだから我々は、論理行作物の最適化計画を使用して、上記のSQLのためのものです:

SQLスパークの旅で
:あなたは記事のスパーク、HadoopのHBaseのかに関連する、マイクロチャネル公衆番号への歓迎の注意に遅れないようにしたい場合はiteblog_hadoop

図から分かるように、列を切断した後、T1とテーブルid値は、2つのフィールドを必要とする; T2は、照会テーブルIDフィールドを必要とします。基礎となるファイル・フォーマットおよび列メモリ(例えば寄木)は、大幅走査速度データを向上させることができる場合、これは、データの送信を低減します。

定数交換

一定の置き換えスパークSQLがされて  ConstantPropagation 実装されています。I = 5テーブルからそのようなSELECT *などの定数、変数、で置換されている AND jは= I + 3は表I = 5 SELECT * FROMに変換することができる AND J = 8。これは私には罰金に見えますが、行数がスキャンされた場合に非常に多くの時間を計算する多くのコストを削減することができます。次のようにこの最適化の後、得られた論理的な計画は次のとおりです。

SQLスパークの旅で
:あなたは記事のスパーク、HadoopのHBaseのかに関連する、マイクロチャネル公衆番号への歓迎の注意に遅れないようにしたい場合はiteblog_hadoop

私たちのお問い合わせは持っている  t1.cid = 1 AND t1.did = t1.cid + 1 という事実から分かるように、クエリは、すでに決定された値をt1.cidので、私たちはt1.didを計算するためにそれを使用することができます。

一定の蓄積

スパークSQLに蓄積された定数がされて  ConstantFolding 実装されています。これと同様の一定の交換は、いくつかの定数式は、事前に計算し、この段階でもありました。この変更は考えにくいが、非常に大量のデータにCPUなどのリソースの使用を減らし、計算時間の多くを減らすことができます。次のようにこの最適化の後、得られた論理的な計画は次のとおりです。

SQLスパークの旅で
:あなたは記事のスパーク、HadoopのHBaseのかに関連する、マイクロチャネル公衆番号への歓迎の注意に遅れないようにしたい場合はiteblog_hadoop

以下のように上記の4つのステップの最適化の後、最適化後の論理計画がありました:

== Optimized Logical Plan ==
Aggregate [sum(cast(v#16 as bigint)) AS sum(v)#22L]
+- Project [(3 + value#1) AS v#16]
   +- Join Inner, (id#0 = id#8)
      :- Project [id#0, value#1]
      :  +- Filter (((((isnotnull(cid#2) && isnotnull(did#3)) && (cid#2 = 1)) && (did#3 = 2)) && (id#0 > 5)) && isnotnull(id#0))
      :     +- Relation[id#0,value#1,cid#2,did#3] csv
      +- Project [id#8]
         +- Filter (isnotnull(id#8) && (id#8 > 5))
            +- Relation[id#8,value#9,cid#10,did#11] csv

对应的图如下:

SQLスパークの旅で
如果想及时了解Spark、Hadoop或者HBase相关的文章,欢迎关注微信公众号:iteblog_hadoop

到这里,优化逻辑计划阶段就算完成了。另外,Spark 内置提供了多达70个优化 Rule,详情请参见 这里

生成可执行的物理计划阶段 - SparkPlanner

前面介绍的逻辑计划在 Spark 里面其实并不能被执行的,为了能够执行这个 SQL,一定需要翻译成物理计划,到这个阶段 Spark 就知道如何执行这个 SQL 了。和前面逻辑计划绑定和优化不一样,这里使用的是策略(Strategy),而且前面介绍的逻辑计划绑定和优化经过 Transformations 动作之后,树的类型并没有改变,也就是说:Expression 经过 Transformations 之后得到的还是 Transformations ;Logical Plan 经过 Transformations 之后得到的还是 Logical Plan。而到了这个阶段,经过 Transformations 动作之后,树的类型改变了,由 Logical Plan 转换成 Physical Plan 了。

一个逻辑计划(Logical Plan)经过一系列的策略处理之后,得到多个物理计划(Physical Plans),物理计划在 Spark 是由 SparkPlan 实现的。多个物理计划再经过代价模型(Cost Model)得到选择后的物理计划(Selected Physical Plan),整个过程如下所示:

SQLスパークの旅で
如果想及时了解Spark、Hadoop或者HBase相关的文章,欢迎关注微信公众号:iteblog_hadoop

Cost Model 对应的就是基于代价的优化(Cost-based Optimizations,CBO,主要由华为的大佬们实现的,详见 SPARK-16026 ),核心思想是计算每个物理计划的代价,然后得到最优的物理计划。但是在目前最新版的 Spark 2.4.3,这一部分并没有实现,直接返回多个物理计划列表的第一个作为最优的物理计划,如下:

lazy val sparkPlan: SparkPlan = {
    SparkSession.setActiveSession(sparkSession)
    // TODO: We use next(), i.e. take the first plan returned by the planner, here for now,
    //       but we will implement to choose the best plan.
    planner.plan(ReturnAnswer(optimizedPlan)).next()
}

而 SPARK-16026 引入的 CBO 优化主要是在前面介绍的优化逻辑计划阶段 - Optimizer 阶段进行的,对应的 Rule 为 CostBasedJoinReorder,并且默认是关闭的,需要通过 spark.sql.cbo.enabled 或 spark.sql.cbo.joinReorder.enabled 参数开启。
所以到了这个节点,最后得到的物理计划如下:

== Physical Plan ==
*(3) HashAggregate(keys=[], functions=[sum(cast(v#16 as bigint))], output=[sum(v)#22L])
+- Exchange SinglePartition
   +- *(2) HashAggregate(keys=[], functions=[partial_sum(cast(v#16 as bigint))], output=[sum#24L])
      +- *(2) Project [(3 + value#1) AS v#16]
         +- *(2) BroadcastHashJoin [id#0], [id#8], Inner, BuildRight
            :- *(2) Project [id#0, value#1]
            :  +- *(2) Filter (((((isnotnull(cid#2) && isnotnull(did#3)) && (cid#2 = 1)) && (did#3 = 2)) && (id#0 > 5)) && isnotnull(id#0))
            :     +- *(2) FileScan csv [id#0,value#1,cid#2,did#3] Batched: false, Format: CSV, Location: InMemoryFileIndex[file:/iteblog/t1.csv], PartitionFilters: [], PushedFilters: [IsNotNull(cid), IsNotNull(did), EqualTo(cid,1), EqualTo(did,2), GreaterThan(id,5), IsNotNull(id)], ReadSchema: struct<id:int,value:int,cid:int,did:int>
            +- BroadcastExchange HashedRelationBroadcastMode(List(cast(input[0, int, true] as bigint)))
               +- *(1) Project [id#8]
                  +- *(1) Filter (isnotnull(id#8) && (id#8 > 5))
                     +- *(1) FileScan csv [id#8] Batched: false, Format: CSV, Location: InMemoryFileIndex[file:/iteblog/t2.csv], PartitionFilters: [], PushedFilters: [IsNotNull(id), GreaterThan(id,5)], ReadSchema: struct<id:int>

上記の結果から分かるように、計画段階の物理的データソースは既に内部から読み出したCSVファイルを知られているだけでなく、パス、データファイルの種類を知っています。そして、ドキュメントを読んで、直接フィルタ条件(PushedFilters)がリストに追加されます。同時に、これはBroadcastHashJoinに参加なる、すなわちノードT1 T2のテーブルに放送データテーブルここ。図は次のとおりです。

SQLスパークの旅で
:あなたは記事のスパーク、HadoopのHBaseのかに関連する、マイクロチャネル公衆番号への歓迎の注意に遅れないようにしたい場合はiteblog_hadoop

ここでは、物理的な計画が完全に生成されます。スペースの理由から、私は、コード生成(WholeStageCodeGen)と関連し、他のものの実装を含む次の記事で紹介SQLの残りの部分を扱いますので、ご期待ください。

より転載過去の記憶(https://www.iteblog.com/)
このリンク:  [Apacheのスパーク旅行でSQL(中)](https://www.iteblog.com/archives/2562.html)

おすすめ

転載: blog.csdn.net/BD_fuhong/article/details/94756337