regroupBy似乎强制重新计算Spark DataFrame

时间:2019-04-17 09:43:23

标签: scala apache-spark apache-spark-2.3

我在使用Scala的Spark 2.3.0时遇到一些奇怪的行为,我需要一些建议。

我有一个DataFrame,我们称之为elemsDF,它看起来像这样:

+--------------------+--------------------+--------+----------+-----------+------------------+------+
|           ref_el_id|              ref_id|time_rel|signalname|signalvalue|standard_deviation|p_date|
+--------------------+--------------------+--------+----------+-----------+------------------+------+
|897cc061-3d02-422...|b6ddddeb-ea26-485...|     0.1|        s1|        1.0|               0.0|201611|
|aecb9ee1-5a7b-4d5...|b6ddddeb-ea26-485...|     0.0|        s1|        0.0|               0.0|201611|
|36e51ce6-f19d-4ff...|f66d637a-5af1-4eb...|     0.1|        s1|        1.0|               0.0|201611|
|2fec8f90-f033-431...|f66d637a-5af1-4eb...|     0.0|        s1|        0.0|               0.0|201611|
+--------------------+--------------------+--------+----------+-----------+------------------+------+

ref_el_idref_id是由UserDefinedFunction在某些时候创建的随机生成的UUID。

import java.util.UUID

def genUuidUdf: UserDefinedFunction = udf(() => UUID.randomUUID().toString)

现在很正常,每次我显示elemsDF时,都会重新计算UUID。

elemsDF.show()
+--------------------+--------------------+--------+----------+-----------+------------------+------+
|           ref_el_id|              ref_id|time_rel|signalname|signalvalue|standard_deviation|p_date|
+--------------------+--------------------+--------+----------+-----------+------------------+------+
|897cc061-3d02-422...|b6ddddeb-ea26-485...|     0.1|        s1|        1.0|               0.0|201611|
|aecb9ee1-5a7b-4d5...|b6ddddeb-ea26-485...|     0.0|        s1|        0.0|               0.0|201611|
|36e51ce6-f19d-4ff...|f66d637a-5af1-4eb...|     0.1|        s1|        1.0|               0.0|201611|
|2fec8f90-f033-431...|f66d637a-5af1-4eb...|     0.0|        s1|        0.0|               0.0|201611|
+--------------------+--------------------+--------+----------+-----------+------------------+------+

elemsDF.show()
+--------------------+--------------------+--------+----------+-----------+------------------+------+
|           ref_el_id|              ref_id|time_rel|signalname|signalvalue|standard_deviation|p_date|
+--------------------+--------------------+--------+----------+-----------+------------------+------+
|e1bfd5a9-91fc-422...|364c9a75-3990-427...|     0.1|        s1|        1.0|               0.0|201611|
|6bfaa133-ee1e-4e9...|364c9a75-3990-427...|     0.0|        s1|        0.0|               0.0|201611|
|6f4fc033-3aa1-4e9...|d3e4f33c-2e3c-423...|     0.1|        s1|        1.0|               0.0|201611|
|d70e66a4-da5d-49c...|d3e4f33c-2e3c-423...|     0.0|        s1|        0.0|               0.0|201611|
+--------------------+--------------------+--------+----------+-----------+------------------+------+

到目前为止,我们坚持使用DataFrame并修复了为UUID计算的值。

elemsDF.persist()

由于persist()是惰性操作,因此需要执行一项操作才能将其激活。再次运行show()可完成此操作。

elemsDF.show()
+--------------------+--------------------+--------+----------+-----------+------------------+------+
|           ref_el_id|              ref_id|time_rel|signalname|signalvalue|standard_deviation|p_date|
+--------------------+--------------------+--------+----------+-----------+------------------+------+
|4a23d926-9bfa-484...|0d67060b-8a76-492...|     0.1|        s1|        1.0|               0.0|201611|
|b1536569-917b-44b...|0d67060b-8a76-492...|     0.0|        s1|        0.0|               0.0|201611|
|325d8e49-c6e6-4b0...|bc575378-0216-46c...|     0.1|        s1|        1.0|               0.0|201611|
|bbcc9c19-95e0-45c...|bc575378-0216-46c...|     0.0|        s1|        0.0|               0.0|201611|
+--------------------+--------------------+--------+----------+-----------+------------------+------+

elemsDF.show()
+--------------------+--------------------+--------+----------+-----------+------------------+------+
|           ref_el_id|              ref_id|time_rel|signalname|signalvalue|standard_deviation|p_date|
+--------------------+--------------------+--------+----------+-----------+------------------+------+
|4a23d926-9bfa-484...|0d67060b-8a76-492...|     0.1|        s1|        1.0|               0.0|201611|
|b1536569-917b-44b...|0d67060b-8a76-492...|     0.0|        s1|        0.0|               0.0|201611|
|325d8e49-c6e6-4b0...|bc575378-0216-46c...|     0.1|        s1|        1.0|               0.0|201611|
|bbcc9c19-95e0-45c...|bc575378-0216-46c...|     0.0|        s1|        0.0|               0.0|201611|
+--------------------+--------------------+--------+----------+-----------+------------------+------+

所以这很有意义。现在,这些值是固定的,不会一遍又一遍地重新计算。

现在奇怪的行为;我尝试使用groupBy和聚合函数,但是,即使在持久保存DataFrame之后,这样做似乎也会在内部强制重新计算。

elemsDF.groupBy("ref_id").agg(count("signalname")).show
+--------------------+---------+                                                
|              ref_id|n_signals|
+--------------------+---------+
|d8ec0aa2-8097-40a...|        2|
|e4071400-8298-410...|        2|
+--------------------+---------+

elemsDF.groupBy("ref_id").agg(count("signalname")).show
+--------------------+-----------------+                                        
|              ref_id|count(signalname)|
+--------------------+-----------------+
|cc206b29-c9ad-49d...|                2|
|454019c4-80ec-449...|                2|
+--------------------+-----------------+

有人可以向我解释这里发生了什么,我应该怎么做才能避免这种行为?

编辑:谢谢@ user10938362,但是链接的问题是关于没有在UDF创建的新列中获得期望的随机值,并且genUuidUdf.asNonDeterministic没什么区别。每次show都没有persist时,仍然会产生不同的UUID,即使持久保存groupBy之后,仍然会强制重新计算并生成新的随机值。

编辑:我的问题被标记为重复,尽管不是建议问题的重复,但它是另一个question的重复。

TL; DR是:不要编写不确定的UDF。

0 个答案:

没有答案