我正在尝试理解火花的物理计划,但我不理解某些部分,因为它们似乎与传统的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
我对该计划的理解是:
首先从Hive表扫描开始
然后使用条件
然后投射以获取我们想要的列
然后TungstenAggregate?
然后是TungstenExchange?
然后TungstenAggregate再次?
然后ConvertToSafe?
然后对最终结果进行排序
但我不理解4,5,6和7步骤。你知道它们是什么吗?我正在寻找有关这方面的信息,所以我可以理解这个计划,但我找不到任何具体的内容。
答案 0 :(得分:20)
让我们看一下您使用的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
/ HiveTableScan
不存在) 1}})FROM
对应#3
子句(#2
)剩余部分可归结如下:
SELECT
来自functions
<{1}} TungstenAggregates
子句 - GROUP BY
字段
#4
子句(TungstenExchange
):
key
/ hash partitioning TungstenAggregates
#6
字段
ORDER BY
- DataFrames
条款。
Project Tungsten通常描述了Spark sets
( - sun.misc.Unsafe
)使用的一组优化,包括:
ConvertToUnsafe
进行显式内存管理。它意味着“本机”(堆外)内存使用和显式内存分配/释放GC管理之外。这些转化对应于执行计划中的ConvertToSafe
/ TungstenAggregate
步骤。您可以从Understanding sun.misc.Unsafe 您可以从Project Tungsten: Bringing Apache Spark Closer to Bare Metal了解有关Tungsten的更多信息。 Apache Spark 2.0: Faster, Easier, and Smarter提供了一些代码生成示例。
reduceByKey
出现两次,因为数据首先在每个分区上本地聚合,而不是混洗,最后合并。如果您熟悉RDD API,则此过程大致相当于DataFrame
。
如果执行计划不明确,您还可以尝试将结果RDD
转换为toDebugString
并分析in >> value
的输出。
答案 1 :(得分:2)
Tungsten是1.4以来Spark中的新内存引擎,它管理JVM外部的数据以节省一些GC开销。您可以想象这样做涉及从JVM复制数据和向JVM复制数据。就是这样。在Spark 1.5中,您可以通过spark.sql.tungsten.enabled
关闭Tungsten,然后您将看到&#34; old&#34;计划,在Spark 1.6中我认为你不能再把它关掉了。