![](/img/trans.png)
[英]Adapting a sliding-window Python generator function to shuffle the window
[英]Data shuffle for Hive and Spark window function
當對已經在同一節點上的數據使用Hive窗口函數時,是否會發生數據混洗?
具體在下面的示例中,在使用窗口函數數據之前,已經使用Spark repartition()函數通過'City'重新分區,這應該確保城市'A'的所有數據共同本地化在同一節點上(假設城市的數據可以適合在一個節點)。
df = sqlContext.createDataFrame(
[('A', '1', 2009, "data1"),
('A', '1', 2015, "data2"),
('A', '22', 2015, "data3"),
('A', '22', 2016, "data4"),
('BB', '333', 2014, "data5"),
('BB', '333', 2012, "data6"),
('BB', '333', 2016, "data7")
],
("City", "Person","year", "data"))
df = df.repartition(2, 'City')
df.show()
# +----+------+----+-----+
# |City|Person|year| data|
# +----+------+----+-----+
# | BB| 333|2012|data6|
# | BB| 333|2014|data5|
# | BB| 333|2016|data7|
# | A| 22|2016|data4|
# | A| 22|2015|data3|
# | A| 1|2009|data1|
# | A| 1|2015|data2|
# +----+------+----+-----+
然后我必須通過'Person'進行窗口函數分區,它不是Spark repartition()中的分區鍵,如下所示。
df.registerTempTable('example')
sqlStr = """\
select *,
row_number() over (partition by Person order by year desc) ranking
from example
"""
sqlContext.sql(sqlStr).show(100)
# +----+------+----+-----+-------+
# |City|Person|year| data|ranking|
# +----+------+----+-----+-------+
# | BB| 333|2016|data7| 1|
# | BB| 333|2014|data5| 2|
# | BB| 333|2012|data6| 3|
# | A| 1|2015|data2| 1|
# | A| 1|2009|data1| 2|
# | A| 22|2016|data4| 1|
# | A| 22|2015|data3| 2|
# +----+------+----+-----+-------+
這是我的問題:
Spark“repartition”和Hive“partition by”之間是否有任何關系或區別? 在引擎蓋下,他們在Spark上翻譯成同樣的東西嗎?
我想檢查一下我的理解是否正確。 即使所有數據已經在同一節點上,如果我調用Spark df.repartition('A_key_different_from_current_partidion_key'),數據也會被混洗到許多節點,而不是在同一節點上保持在一起。
順便說一句,我也很好奇用Spark窗口函數實現示例Hive查詢是否簡單。
窗口函數和repartition
中的partition by
子句都執行相同的TungstenExchange
機制。 分析執行計划時會看到這個:
sqlContext.sql(sqlStr).explain()
## == Physical Plan ==
## Window [City#0,Person#1,year#2L,data#3], [HiveWindowFunction#org.apache.hadoop.hive.ql.udf.generic.GenericUDAFRowNumber() windowspecdefinition(Person#1,year#2L DESC,ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) AS ranking#5], [Person#1], [year#2L DESC]
## +- Sort [Person#1 ASC,year#2L DESC], false, 0
## +- TungstenExchange hashpartitioning(Person#1,200), None <- PARTITION BY
## +- Project [City#0,Person#1,year#2L,data#3]
## +- TungstenExchange hashpartitioning(City#0,2), None <- REPARTITION
## +- ConvertToUnsafe
## +- Scan ExistingRDD[City#0,Person#1,year#2L,data#3]
關於第二個問題,你的假設是正確的。 即使數據已經位於單個節點上,Spark也沒有關於數據分發的先驗知識,並且會再次對數據進行混洗。
最后,根據一種觀點,您的查詢已經是Spark查詢,或者使用普通Spark無法執行此操作。
它是一個Spark查詢,因為DSL對應物將使用完全相同的機制
from pyspark.sql.window import Window from pyspark.sql.functions import col, row_number w = Window.partitionBy("person").orderBy(col("year").desc()) df.withColumn("ranking", row_number().over(w))
使用普通的Spark無法執行此操作,因為從Spark 1.6開始,沒有窗口函數的本機實現。 它在Spark 2.0中發生了變化。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.