Saltar a contenido

KSQL Joins

Uniones en SQL

JoinTypes.png

ksqlDB soporta tres tipos de join (m谩s info en Join Capabilities):

  • Stream-Stream Joins: ksqlDB soporta INNER, LEFT OUTER (tambi茅n llamado LEFT JOIN), RIGHT OUTER, y FULL OUTER (tambi茅n llamado OUTER JOIN) joins entre streams. Estos joins se definen sobre ventanas de datos de acuerdo con la naturaleza continua de los streams. Cada ventana define el per铆odo de tiempo durante el cual los mensajes son considerados v谩lidos para el join. Con cada mensaje se asocia un per铆odo de gracia que determina el lapso de tiempo admitido fuera de la ventana de tiempo. Para m谩s informaci贸n al respecto ver Time and Windows
  • Stream-Table Joins: ksqlDB soporta INNER y LEFT joins entre un stream y una table. OUTER joins no son soportados. Este tipo de join act煤a como un buscador en la tabla lo cual permite enriquecer el stream con los datos que contiene. Las uniones flujo-tabla siempre son sin ventana
  • Table-Table Joins: ksqlDB admite uniones (1:1) y (1:N) entre tablas, pero no uniones de muchos a muchos (N:M). Para las uniones de clave externa, se puede utilizar cualquier columna de la tabla izquierda en la condici贸n de uni贸n con la clave primaria de la tabla derecha. Las uniones INNER, LEFT OUTER y FULL OUTER son compatibles con las uniones de clave primaria. Mientras que las uniones N-way son generalmente soportadas, las uniones FULL OUTER N-way requieren m煤ltiples consultas separadas, cada una realizando una 煤nica uni贸n FULL OUTER
-- Ejemplo de union stream-table
CREATE STREAM pageviews_enriched AS
SELECT users.userid AS userid, pageid, regionid, gender
FROM pageviews
LEFT JOIN users ON pageviews.userid = users.userid
EMIT CHANGES;

-- Ejemplo de uni贸n entre tres streams
CREATE STREAM shipped_orders AS
  SELECT
     o.id as orderId,
     o.itemid as itemId,
     s.id as shipmentId,
     p.id as paymentId
  FROM orders o
     INNER JOIN payments p WITHIN 1 HOURS ON p.id = o.id
     INNER JOIN shipments s WITHIN 2 HOURS ON s.id = o.id;

Requisitos del Join (m谩s detalle en Partition Data to Enable Joins)

Para unir streams estos deber谩n estar coparticionados (ver informaci贸n detallada en Co-partitioning Requirements) lo que significa que los registros de entrada de ambos lados de la uni贸n tienen el mismo esquema de particionadolos mismos ajustes de configuraci贸n para las particiones. Las uniones entre tablas no tienen ning煤n requisito de copartici贸n. Esto es debido a que para unir dos fuentes de datos, flujos o tablas, ksqlDB necesita comparar sus registros bas谩ndose en la columna de uni贸n. Para garantizar que los registros con la misma columna de uni贸n est茅n ubicados en la misma tarea del flujo, la columna de uni贸n debe coincidir con la columna por la que se particionan las fuentes

Las tablas siempre se particionan por su clave primaria y ksqlDB no permite la repartici贸n de tablas lo que significa que s贸lo se puede utilizar la clave primaria de una tabla como columna de uni贸n. Los streams no tienen claves primarias pero tienen una columna KEY opcional. Una columna KEY, cuando est谩 presente, define la columna de partici贸n

Los flujos permiten uniones en expresiones distintas de su columna clave. Cuando los criterios de uni贸n difieren de la columna KEY, ksqlDB reparte internamente el flujo, lo que impl铆citamente define la clave y el particionado correctos

El siguiente ejemplo muestra una tabla users unida con un stream clicks por la columna userId. La tabla tiene una clave primaria id del mismo tipo SQL. El stream no tiene una clave definida por lo que ksqlDB lo reparticiona autom谩ticamente en la columna de uni贸n (userId) para asignar la clave antes de realizar la uni贸n

-- clicks stream, with no or unknown key.
-- the schema of stream clicks is: USERID BIGINT | URL STRING
CREATE STREAM clicks (
    userId BIGINT,
    url STRING
  ) WITH (
    kafka_topic='clickstream',
    value_format='json',
    partitions=1
  );

-- users table, with userId primary key.
-- the schema of table users is: USERID BIGINT PRIMARY KEY | FULLNAME STRING
CREATE TABLE users (
    id BIGINT PRIMARY KEY,
    fullName STRING
  ) WITH (
    kafka_topic='users',
    value_format='json',
    partitions=1
);

-- join of users table with clicks stream, joining on the table's primary key and the stream's userId column:
-- join will automatically repartition clicks stream:
SELECT
  c.userId,
  c.url,
  u.fullName
FROM clicks c
  JOIN users u ON c.userId = u.id
EMIT CHANGES;