SparkSql 动态添加一列递增序列

文章目录

  • zipWithIndex
    • 效果:
    • 示例
  • zipWithUniqueId
    • 效果:
    • 示例
  • monotonically_increasing_id
    • 效果:
    • 示例
  • 小结:

zipWithIndex

效果:

将此RDD与其元素索引进行Zips。排序首先基于分区索引,然后是每个分区内项目的排序
因此,第一个分区中的第一个项目得到索引0,最后一个分区中最后一个项目得到最大的索引。
这类似于Scala的zipWithIndex,但它使用Long而不是Int作为索引类型。当此RDD包含多个分区时,此方法需要触发spark job。

示例

  • rdd
scala> var rdd2 = sc.makeRDD(Seq("A","B","R","D","F"),2)
rdd2: org.apache.spark.rdd.RDD[String] = ParallelCollectionRDD[34] at makeRDD at :21
 
scala> rdd2.zipWithIndex().collect
res27: Array[(String, Long)] = Array((A,0), (B,1), (R,2), (D,3), (F,4))
  • df
val df1 = Seq((1, "Tom"), (2, "Jack"), (3, "Marry"), (4, "Daniel")).toDF("id", "name")

def addColumns(df: DataFrame): DataFrame = session.sqlContext.createDataFrame(
      df.rdd.zipWithIndex().map{
        case (row,columnsIndex)=>
          println(df.rdd.getNumPartitions)
          Row.fromSeq(row.toSeq :+ columnsIndex)
      },
      //在原有的df的基础上加上index结构
      StructType(df.schema.fields :+ StructField("index",LongType,false))
    )
 val df2: DataFrame = addColumns(df1)
    df2.show(false)
 
	 +---+------+-----+
	|id |name  |index|
	+---+------+-----+
	|4  |Daniel|0    |
	|1  |Tom   |1    |
	|2  |Jack  |2    |
	|3  |Marry |3    |
	+---+------+-----+

zipWithUniqueId

效果:

使用生成的唯一 Long id 压缩此 RDD。第 k 个分区中的项目将获得 id k、n+k、2n+k、…,其中 n 是分区数。
所以可能存在间隙,但是这种方法不会触发spark job,这一点与zipWithIndex不同

示例

scala> var rdd1 = sc.makeRDD(Seq("A","B","C","D","E","F"),2)
rdd1: org.apache.spark.rdd.RDD[String] = ParallelCollectionRDD[44] at makeRDD at :21
//rdd1有两个分区,
 
scala> rdd1.zipWithUniqueId().collect
res32: Array[(String, Long)] = Array((A,0), (B,2), (C,4), (D,1), (E,3), (F,5))
//总分区数为2
//第一个分区第一个元素ID为0,第二个分区第一个元素ID为1
//第一个分区第二个元素ID为0+2=2,第一个分区第三个元素ID为2+2=4
//第二个分区第二个元素ID为1+2=3,第二个分区第三个元素ID为3+2=5

monotonically_increasing_id

效果:

生成单调递增的 64 位整数的列表达式。生成的 ID 保证单调递增且唯一,但不是连续的

示例

Seq((1, "Tom"), (2, "Jack"), (3, "Marry"), (4, "Daniel")).toDF("id", "name").createOrReplaceTempView("info1")

    //准备提交的3个sql
    val sql1 = {
      """
        |select *
        |from info1
      """.stripMargin
    }
    val reparDF: Dataset[Row] = session.sql(sql1).repartition(3)
    println(reparDF.rdd.getNumPartitions)
    reparDF
      .withColumn("index",monotonically_increasing_id)
      .show(false)
	+---+------+-----------+
	|id |name  |index      |
	+---+------+-----------+
	|4  |Daniel|0          |
	|1  |Tom   |8589934592 |
	|2  |Jack  |8589934593 |
	|3  |Marry |17179869184|
	+---+------+-----------+

小结:

  1. 单分区全局有序可以用 monotonically_increasing_id
  2. 多分区全局有序用 zipWithIndex

你可能感兴趣的:(scala,spark,开发语言)