sql >> Databáze >  >> RDS >> PostgreSQL

Primární klíče s Apache Spark

Scala :

Pokud vše, co potřebujete, jsou jedinečná čísla, můžete použít zipWithUniqueId a znovu vytvořit DataFrame. Nejprve nějaké importy a fiktivní data:

import sqlContext.implicits._
import org.apache.spark.sql.Row
import org.apache.spark.sql.types.{StructType, StructField, LongType}

val df = sc.parallelize(Seq(
    ("a", -1.0), ("b", -2.0), ("c", -3.0))).toDF("foo", "bar")

Rozbalte schéma pro další použití:

val schema = df.schema

Přidat pole ID:

val rows = df.rdd.zipWithUniqueId.map{
   case (r: Row, id: Long) => Row.fromSeq(id +: r.toSeq)}

Vytvořit DataFrame:

val dfWithPK = sqlContext.createDataFrame(
  rows, StructType(StructField("id", LongType, false) +: schema.fields))

Totéž v Pythonu :

from pyspark.sql import Row
from pyspark.sql.types import StructField, StructType, LongType

row = Row("foo", "bar")
row_with_index = Row(*["id"] + df.columns)

df = sc.parallelize([row("a", -1.0), row("b", -2.0), row("c", -3.0)]).toDF()

def make_row(columns):
    def _make_row(row, uid):
        row_dict = row.asDict()
        return row_with_index(*[uid] + [row_dict.get(c) for c in columns])
    return _make_row

f = make_row(df.columns)

df_with_pk = (df.rdd
    .zipWithUniqueId()
    .map(lambda x: f(*x))
    .toDF(StructType([StructField("id", LongType(), False)] + df.schema.fields)))

Pokud dáváte přednost pořadovým číslům, můžete nahradit zipWithUniqueId pomocí zipWithIndex ale je to trochu dražší.

Přímo pomocí DataFrame API :

(univerzální Scala, Python, Java, R s téměř stejnou syntaxí)

Dříve mi chybělo monotonicallyIncreasingId funkce, která by měla fungovat dobře, pokud nepotřebujete po sobě jdoucí čísla:

import org.apache.spark.sql.functions.monotonicallyIncreasingId

df.withColumn("id", monotonicallyIncreasingId).show()
// +---+----+-----------+
// |foo| bar|         id|
// +---+----+-----------+
// |  a|-1.0|17179869184|
// |  b|-2.0|42949672960|
// |  c|-3.0|60129542144|
// +---+----+-----------+

Užitečné monotonicallyIncreasingId je nedeterministický. Nejenže se ID mohou lišit provedení od provedení, ale bez dalších triků je nelze použít k identifikaci řádků, když následné operace obsahují filtry.

Poznámka :

Je také možné použít rowNumber funkce okna:

from pyspark.sql.window import Window
from pyspark.sql.functions import rowNumber

w = Window().orderBy()
df.withColumn("id", rowNumber().over(w)).show()

Bohužel:

Okno WARN:Není definován žádný oddíl pro ovládání okna! Přesunutí všech dat do jednoho oddílu může způsobit vážné snížení výkonu.

Pokud tedy nemáte přirozený způsob, jak svá data rozdělit a zajistit jedinečnost, není v tuto chvíli příliš užitečné.



  1. vybrat z jedné tabulky, vložit do jiné tabulky dotaz Oracle SQL

  2. ORA-01950:žádná oprávnění pro tabulkový prostor 'USERS'

  3. Základy tabulkových výrazů, část 8 – CTE, úvahy o optimalizaci pokračovaly

  4. Duplikování tabulky, indexů a dat MySQL