簡體   English   中英

Hive和Spark窗口函數的數據隨機播放

[英]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|
# +----+------+----+-----+-------+

這是我的問題:

  1. Spark“repartition”和Hive“partition by”之間是否有任何關系或區別? 在引擎蓋下,他們在Spark上翻譯成同樣的東西嗎?

  2. 我想檢查一下我的理解是否正確。 即使所有數據已經​​在同一節點上,如果我調用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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM