web-dev-qa-db-ja.com

理解spark物理的計画

sparkの物理的な計画を理解しようとしていますが、一部の部分は従来のrdbmsとは異なるため、理解できません。たとえば、以下のこの計画では、 Hiveテーブル。クエリは次のとおりです。

select
        l_returnflag,
        l_linestatus,
        sum(l_quantity) as sum_qty,
        sum(l_extendedprice) as sum_base_price,
        sum(l_extendedprice * (1 - l_discount)) as sum_disc_price,
        sum(l_extendedprice * (1 - l_discount) * (1 + l_tax)) as sum_charge,
        avg(l_quantity) as avg_qty,
        avg(l_extendedprice) as avg_price,
        avg(l_discount) as avg_disc,
        count(*) as count_order
    from
        lineitem
    where
        l_shipdate <= '1998-09-16'
    group by
        l_returnflag,
        l_linestatus
    order by
        l_returnflag,
        l_linestatus;


== Physical Plan ==
Sort [l_returnflag#35 ASC,l_linestatus#36 ASC], true, 0
+- ConvertToUnsafe
   +- Exchange rangepartitioning(l_returnflag#35 ASC,l_linestatus#36 ASC,200), None
      +- ConvertToSafe
         +- TungstenAggregate(key=[l_returnflag#35,l_linestatus#36], functions=[(sum(l_quantity#31),mode=Final,isDistinct=false),(sum(l_extendedpr#32),mode=Final,isDistinct=false),(sum((l_extendedprice#32 * (1.0 - l_discount#33))),mode=Final,isDistinct=false),(sum(((l_extendedprice#32 * (1.0l_discount#33)) * (1.0 + l_tax#34))),mode=Final,isDistinct=false),(avg(l_quantity#31),mode=Final,isDistinct=false),(avg(l_extendedprice#32),mode=Fl,isDistinct=false),(avg(l_discount#33),mode=Final,isDistinct=false),(count(1),mode=Final,isDistinct=false)], output=[l_returnflag#35,l_linestatus,sum_qty#0,sum_base_price#1,sum_disc_price#2,sum_charge#3,avg_qty#4,avg_price#5,avg_disc#6,count_order#7L])
            +- TungstenExchange hashpartitioning(l_returnflag#35,l_linestatus#36,200), None
               +- TungstenAggregate(key=[l_returnflag#35,l_linestatus#36], functions=[(sum(l_quantity#31),mode=Partial,isDistinct=false),(sum(l_exdedprice#32),mode=Partial,isDistinct=false),(sum((l_extendedprice#32 * (1.0 - l_discount#33))),mode=Partial,isDistinct=false),(sum(((l_extendedpri32 * (1.0 - l_discount#33)) * (1.0 + l_tax#34))),mode=Partial,isDistinct=false),(avg(l_quantity#31),mode=Partial,isDistinct=false),(avg(l_extendedce#32),mode=Partial,isDistinct=false),(avg(l_discount#33),mode=Partial,isDistinct=false),(count(1),mode=Partial,isDistinct=false)], output=[l_retulag#35,l_linestatus#36,sum#64,sum#65,sum#66,sum#67,sum#68,count#69L,sum#70,count#71L,sum#72,count#73L,count#74L])
                  +- Project [l_discount#33,l_linestatus#36,l_tax#34,l_quantity#31,l_extendedprice#32,l_returnflag#35]
                     +- Filter (l_shipdate#37 <= 1998-09-16)
                        +- HiveTableScan [l_discount#33,l_linestatus#36,l_tax#34,l_quantity#31,l_extendedprice#32,l_shipdate#37,l_returnflag#35], astoreRelation default, lineitem, None

私が計画で理解していることは:

  1. 最初にHiveテーブルスキャンを開始します

  2. 次に、条件を使用してフィルタリングします

  3. 次に、必要な列を取得するために投影します

  4. 次に、TungstenAggregate?

  5. 次に、TungstenExchange?

  6. その後、TungstenAggregate?

  7. 次にConvertToSafe?

  8. 次に、最終結果を並べ替えます

しかし、私は4、5、6、7ステップを理解していません。あなたは彼らが何であるか知っていますか?計画を理解できるように、これについての情報を探していますが、具体的なことは何も見つかりません。

21
codin

使用するSQLクエリの構造を見てみましょう。

_SELECT
    ...  -- not aggregated columns  #1
    ...  -- aggregated columns      #2
FROM
    ...                          -- #3
WHERE
    ...                          -- #4
GROUP BY
    ...                          -- #5
ORDER BY
    ...                          -- #6
_

あなたがすでに疑っているように:

  • Filter (...)は、WHERE句の述語に対応します(_#4_)
  • _Project ..._は、列の数を(_#1_と_#2_の和集合で必要なものに制限します。_#4_/_#6_がSELECTにない場合)
  • HiveTableScanFROM句に対応します(_#3_)

残りのパーツは次のように帰属できます。

  • _#2_ from SELECT句-functionsTungstenAggregatesフィールド
  • _GROUP BY_句(_#5_):

    • TungstenExchange /ハッシュ分割
    • keyTungstenAggregatesフィールド
  • _#6_-_ORDER BY_句。

Project Tungstenは、一般的にSpark DataFrames(-sets)が使用する一連の最適化について説明しています。

  • _Sun.misc.Unsafe_による明示的なメモリ管理。これは、「ネイティブ」(ヒープ以外)のメモリ使用量と明示的なメモリ割り当て/ GC管理外での解放を意味します。これらの変換は、実行プランのConvertToUnsafe/ConvertToSafeステップに対応しています。 unsafeに関する興味深い詳細は nderstanding Sun.misc.Unsafe から学ぶことができます。
  • コード生成-コンパイル時に最適化されるコードを生成するように設計されたさまざまなメタプログラミングトリック。あなたはそれを内部のSparkコンパイラと考えることができます。これは、Nice関数コードを醜いforループに書き換えるようなものです。

Project Tungsten:Bringing Apache Spark Closer to Bare MetalApache Spark = 2.0:より速く、より簡単で、よりスマート コード生成の例をいくつか示します。

TungstenAggregateが2回発生するのは、データが最初に各パーティションでローカルに集計されてから、シャッフルされ、最後にマージされるためです。 RDD APIに精通している場合、このプロセスはreduceByKeyとほぼ同じです。

実行計画が明確でない場合は、結果のDataFrameRDDに変換して、toDebugStringの出力を分析することもできます。

26
zero323

タングステンは、1.4以降のSparkの新しいメモリエンジンであり、JVMの外部でデータを管理して、GCのオーバーヘッドを節約します。 JVMとの間でデータをコピーすることを想像してみてください。それでおしまい。 Spark 1.5ではspark.sql.tungsten.enabledを介してタングステンをオフにでき、「古い」プランがSparkに表示されます1.6もうオフにできないと思います。

3
piggybox