Introducción a los siete tipos de combinación admitidos en Apache Spark

Introducción a los siete tipos de combinación admitidos en Apache Spark

Big Data de memoria pasada Big Data de memoria pasada

En el análisis de datos, es un escenario muy común realizar una operación de unión en dos conjuntos de datos. En este artículo, presenté las cinco estrategias de combinación admitidas por Spark. En este artículo, le presentaré el tipo de combinación admitido en Apache Spark.

En la versión actual de Apache Spark 3.0, se admiten los siguientes siete tipos de combinación:

• INNER JOIN
• CROSS JOIN
• IZQUIERDA EXTERIOR JOIN
• DERECHA EXTERIOR JOIN
• FULL EXTERIOR JOIN
• IZQUIERDA SEMI JOIN
• IZQUIERDA ANTI JOIN
En términos de implementación, las clases de implementación correspondientes a estos siete tipos de Join son las siguientes:


object JoinType {
  def apply(typ: String): JoinType = typ.toLowerCase(Locale.ROOT).replace("_", "") match {
    case "inner" => Inner
    case "outer" | "full" | "fullouter" => FullOuter
    case "leftouter" | "left" => LeftOuter
    case "rightouter" | "right" => RightOuter
    case "leftsemi" | "semi" => LeftSemi
    case "leftanti" | "anti" => LeftAnti
    case "cross" => Cross
    case _ =>
      val supported = Seq(
        "inner",
        "outer", "full", "fullouter", "full_outer",
        "leftouter", "left", "left_outer",
        "rightouter", "right", "right_outer",
        "leftsemi", "left_semi", "semi",
        "leftanti", "left_anti", "anti",
        "cross")
      throw new IllegalArgumentException(s"Unsupported join type '$typ'. " +
        "Supported join types include: " + supported.mkString("'", "', '", "'") + ".")
  }
}

Hoy, no pretendo presentar la implementación de estos siete tipos de Join desde el código subyacente, sino desde la perspectiva de un analista de datos para presentar el significado y uso de estos tipos de Join. Antes de introducir lo siguiente, suponga que tenemos dos tablas relacionadas con el cliente y el pedido, de la siguiente manera:


scala> val order = spark.sparkContext.parallelize(Seq(
     |   (1, 101,2500), (2,102,1110), (3,103,500), (4 ,102,400)
     | )).toDF("paymentId", "customerId","amount")
order: org.apache.spark.sql.DataFrame = [paymentId: int, customerId: int ... 1 more field]
scala> order.show
+---------+----------+------+
|paymentId|customerId|amount|
+---------+----------+------+
|        1|       101|  2500|
|        2|       102|  1110|
|        3|       103|   500|
|        4|       102|   400|
+---------+----------+------+
scala> val customer = spark.sparkContext.parallelize(Seq(
     |     (101,"iteblog") ,(102,"iteblog_hadoop") ,(103,"iteblog001"), (104,"iteblog002"), (105,"iteblog003"), (106,"iteblog004")
     | )).toDF("customerId", "name")
customer: org.apache.spark.sql.DataFrame = [customerId: int, name: string]
scala> customer.show
+----------+--------------+
|customerId|          name|
+----------+--------------+
|       101|       iteblog|
|       102|iteblog_hadoop|
|       103|    iteblog001|
|       104|    iteblog002|
|       105|    iteblog003|
|       106|    iteblog004|
+----------+--------------+
准备好数据之后,现在我们来一一介绍这些 Join 类型。

UNIR INTERNAMENTE

En Spark, si no se especifica ningún tipo de unión, el valor predeterminado es INNER JOIN. INNER JOIN solo devolverá datos que cumplan con la condición de combinación. Esto debe usarse con más frecuencia, de la siguiente manera:


scala> val df = customer.join(order,"customerId")
df: org.apache.spark.sql.DataFrame = [customerId: int, name: string ... 2 more fields]
scala> df.show
+----------+--------------+---------+------+
|customerId|          name|paymentId|amount|
+----------+--------------+---------+------+
|       101|       iteblog|        1|  2500|
|       103|    iteblog001|        3|   500|
|       102|iteblog_hadoop|        2|  1110|
|       102|iteblog_hadoop|        4|   400|
+----------+--------------+---------+------+

Como se puede ver en lo anterior, cuando no especificamos ningún tipo de Join, el valor predeterminado es INNER JOIN; en el resultado generado, Spark elimina automáticamente el customerId que existe en ambas tablas para nosotros. Si se representa mediante un gráfico, INNER JOIN se puede representar de la siguiente manera:

Introducción a los siete tipos de combinación admitidos en Apache Spark

La parte rosa de la imagen de arriba es el resultado de INNER JOIN.

ÚNETE CRUZADO

Este tipo de combinación también se denomina producto cartesiano (producto cartesiano). Cada fila de datos en la tabla izquierda de combinación se unirá con cada fila de datos en la tabla derecha. El número resultante de filas es m * n, por lo que en un entorno de producción Intente no utilizar este tipo de combinación. El siguiente es un ejemplo del uso de CROSS JOIN:


scala> val df = customer.crossJoin(order)
df: org.apache.spark.sql.DataFrame = [customerId: int, name: string ... 3 more fields]
scala> df.show
+----------+--------------+---------+----------+------+
|customerId|          name|paymentId|customerId|amount|
+----------+--------------+---------+----------+------+
|       101|       iteblog|        1|       101|  2500|
|       101|       iteblog|        2|       102|  1110|
|       101|       iteblog|        3|       103|   500|
|       101|       iteblog|        4|       102|   400|
|       102|iteblog_hadoop|        1|       101|  2500|
|       102|iteblog_hadoop|        2|       102|  1110|
|       102|iteblog_hadoop|        3|       103|   500|
|       102|iteblog_hadoop|        4|       102|   400|
|       103|    iteblog001|        1|       101|  2500|
|       103|    iteblog001|        2|       102|  1110|
|       103|    iteblog001|        3|       103|   500|
|       103|    iteblog001|        4|       102|   400|
|       104|    iteblog002|        1|       101|  2500|
|       104|    iteblog002|        2|       102|  1110|
|       104|    iteblog002|        3|       103|   500|
|       104|    iteblog002|        4|       102|   400|
|       105|    iteblog003|        1|       101|  2500|
|       105|    iteblog003|        2|       102|  1110|
|       105|    iteblog003|        3|       103|   500|
|       105|    iteblog003|        4|       102|   400|
+----------+--------------+---------+----------+------+
only showing top 20 rows

IZQUIERDA COMBINACIÓN EXTERNA

LEFT OUTER JOIN es equivalente a LEFT JOIN. Creo que todos conocen el resultado devuelto por este Join, así que no lo presentaré. Las siguientes tres redacciones son equivalentes:


val leftJoinDf = customer.join(order,Seq("customerId"), "left_outer")
val leftJoinDf = customer.join(order,Seq("customerId"), "leftouter")
val leftJoinDf = customer.join(order,Seq("customerId"), "left")
scala> leftJoinDf.show
+----------+--------------+---------+------+
|customerId|          name|paymentId|amount|
+----------+--------------+---------+------+
|       101|       iteblog|        1|  2500|
|       103|    iteblog001|        3|   500|
|       102|iteblog_hadoop|        2|  1110|
|       102|iteblog_hadoop|        4|   400|
|       105|    iteblog003|     null|  null|
|       106|    iteblog004|     null|  null|
|       104|    iteblog002|     null|  null|
+----------+--------------+---------+------+

Si está representado por una figura, el LEFT OUTER JOIN puede ser el siguiente: Se puede ver que se mostrarán los datos de la tabla de la izquierda que participan en el Join, y la tabla de la derecha solo se mostrará si está relacionada.

Introducción a los siete tipos de combinación admitidos en Apache Spark

UNIÓN EXTERIOR DERECHA

Similar a LEFT OUTER JOIN, RIGHT OUTER JOIN es equivalente a RIGHT JOIN, y las siguientes tres formas de escritura también son equivalentes:


val rightJoinDf = order.join(customer,Seq("customerId"), "right")
val rightJoinDf = order.join(customer,Seq("customerId"), "right_outer")
val rightJoinDf = order.join(customer,Seq("customerId"), "rightouter")
scala> rightJoinDf.show
+----------+---------+------+--------------+
|customerId|paymentId|amount|          name|
+----------+---------+------+--------------+
|       101|        1|  2500|       iteblog|
|       103|        3|   500|    iteblog001|
|       102|        2|  1110|iteblog_hadoop|
|       102|        4|   400|iteblog_hadoop|
|       105|     null|  null|    iteblog003|
|       106|     null|  null|    iteblog004|
|       104|     null|  null|    iteblog002|
+----------+---------+------+--------------+

Si está representado por una figura, el JOIN EXTERIOR DERECHO puede ser el siguiente: Se puede ver que se mostrarán los datos de la tabla derecha que participa en el Join, y la tabla de la izquierda solo se mostrará si está relacionada.

Introducción a los siete tipos de combinación admitidos en Apache Spark

UNIÓN EXTERIOR COMPLETA

Todo el mundo debería estar familiarizado con el significado de FULL OUTER JOIN, por lo que no presentaré su significado. FULL OUTER JOIN tiene las siguientes cuatro formas de escritura:


val fullJoinDf = order.join(customer,Seq("customerId"), "outer")
val fullJoinDf = order.join(customer,Seq("customerId"), "full")
val fullJoinDf = order.join(customer,Seq("customerId"), "full_outer")
val fullJoinDf = order.join(customer,Seq("customerId"), "fullouter")
scala> fullJoinDf.show
+----------+---------+------+--------------+
|customerId|paymentId|amount|          name|
+----------+---------+------+--------------+
|       101|        1|  2500|       iteblog|
|       103|        3|   500|    iteblog001|
|       102|        2|  1110|iteblog_hadoop|
|       102|        4|   400|iteblog_hadoop|
|       105|     null|  null|    iteblog003|
|       106|     null|  null|    iteblog004|
|       104|     null|  null|    iteblog002|
+----------+---------+------+--------------+

FULL OUTER JOIN se puede representar mediante la siguiente figura:

Introducción a los siete tipos de combinación admitidos en Apache Spark

SEMI UNIRSE A LA IZQUIERDA

Hay relativamente pocas personas que deberían saber LEFT SEMI JOIN. LEFT SEMI JOIN solo devolverá los datos que coincidan con la tabla de la derecha, y LEFT SEMI JOIN solo devolverá los datos de la tabla de la izquierda, los datos de la tabla de la derecha no se mostrarán , los siguientes tres Los métodos de escritura son todos equivalentes:


val leftSemiJoinDf = order.join(customer,Seq("customerId"), "leftsemi")
val leftSemiJoinDf = order.join(customer,Seq("customerId"), "left_semi")
val leftSemiJoinDf = order.join(customer,Seq("customerId"), "semi")
scala> leftSemiJoinDf.show
+----------+---------+------+
|customerId|paymentId|amount|
+----------+---------+------+
|       101|        1|  2500|
|       103|        3|   500|
|       102|        2|  1110|
|       102|        4|   400|
+----------+---------+------+

Como se puede ver en los resultados anteriores, LEFT SEMI JOIN en realidad se puede reescribir con IN / EXISTS:


scala> order.registerTempTable("order")
warning: there was one deprecation warning (since 2.0.0); for details, enable `:setting -deprecation' or `:replay -deprecation'
scala> customer.registerTempTable("customer")
warning: there was one deprecation warning (since 2.0.0); for details, enable `:setting -deprecation' or `:replay -deprecation'
scala> val r = spark.sql("select * from order where customerId in (select customerId from customer)")
r: org.apache.spark.sql.DataFrame = [paymentId: int, customerId: int ... 1 more field]
scala> r.show
+---------+----------+------+
|paymentId|customerId|amount|
+---------+----------+------+
|        1|       101|  2500|
|        3|       103|   500|
|        2|       102|  1110|
|        4|       102|   400|
+---------+----------+------+

LEFT SEMI JOIN se puede representar mediante la siguiente figura:

Introducción a los siete tipos de combinación admitidos en Apache Spark

IZQUIERDA ANTIUNIR

A diferencia de LEFT SEMI JOIN, LEFT ANTI JOIN solo devolverá datos de la tabla de la izquierda que no coincidan con la tabla de la derecha. Y las siguientes tres formas de escribir también son equivalentes:


val leftAntiJoinDf = customer.join(order,Seq("customerId"), "leftanti")
val leftAntiJoinDf = customer.join(order,Seq("customerId"), "left_anti")
val leftAntiJoinDf = customer.join(order,Seq("customerId"), "anti")
scala> leftAntiJoinDf.show
+----------+----------+
|customerId|      name|
+----------+----------+
|       105|iteblog003|
|       106|iteblog004|
|       104|iteblog002|
+----------+----------+

De la misma manera, LEFT ANTI JOIN también se puede reescribir con NOT IN:


scala> val r = spark.sql("select * from customer where customerId not in (select customerId from order)")
r: org.apache.spark.sql.DataFrame = [customerId: int, name: string]
scala> r.show
+----------+----------+
|customerId|      name|
+----------+----------+
|       104|iteblog002|
|       105|iteblog003|
|       106|iteblog004|
+----------+----------+

IZQUIERDA SEMI ANTI se puede representar con la siguiente figura:

Introducción a los siete tipos de combinación admitidos en Apache Spark

Bien, se han presentado brevemente los siete tipos de Join de Spark. Puede elegir diferentes tipos de Join de acuerdo con los diferentes tipos de escenarios comerciales. Eso es todo por compartir hoy, gracias por su atención y apoyo.

Supongo que te gusta

Origin blog.51cto.com/15127589/2678048
Recomendado
Clasificación