In einem Blogbeitrag Ende des letzten Jahres haben wir einen Überblick der verschiedenen Prinzipien von Talend gegeben. Der Fokus lag hier auf den vielen Freiheiten, die dieses Tool bietet. Weiterhin ist am Anfang dieses Jahres ein Blogbeitrag erschienen, der die Vorteile eines gut gepflegten Java-Code Repositorys beschreibt und außerdem eine Möglichkeit darstellt dynamische Datenbankabfragen zu definieren.
Der heutige Beitrag stellt das Herzstück vieler Talend Jobs in den Mittelpunkt: die vielseitig einsetzbare Komponente tMap. Diese Komponente vereint nicht nur andere native Komponenten, wie beispielsweise tJoin und tFilterRow miteinander, sondern liefert auch wichtige Features, die sonst keine andere Komponente bedienen kann.
Reihenfolge und Durchreichen der Zeilen
Wie viele andere Talend Komponenten auch, ändert die tMap die Zeilenreihenfolge nicht und gibt die einzelnen Zeilen direkt zur nächsten Komponente weiter. Bei einem simplen Mapping mit nur einem Input, Output und mit einer oder mehreren tMaps dazwischen, können die Daten schon im Ziel geschrieben werden, obwohl der Input noch nicht alle Zeilen eingelesen hat. Diese Eigenschaft ist vor allem bei großen Datenmengen enorm vorteilhaft, da die Gesamtmenge an Daten nicht im Arbeitsspeicher vorgehalten werden muss und weiterhin parallel gelesen und geschrieben werden kann.
Filtern und Duplizieren
Die Anzahl der Zeilen am tMap-Ausgang muss nicht zwangsläufig der Anzahl am Eingang entsprechen. Zum einen lassen sich Filterbedingungen definieren, die die Anzahl der Zeilen verringern, und zum anderen lassen sich die Zeilen auch duplizieren. Die tMap bietet die Möglichkeit mehrere Ausgangsströme zu definieren (analog der Informatica Komponente Router). Sind zum Beispiel 2 Ausgangsströme definiert, die jeweils keine Filterbedingungen haben, so ist die Anzahl der Zeilen am Ausgang der tMap zusammengezählt doppelt so hoch.
Dieser Beispieljob zeigt die verschiedenen Möglichkeiten die Zeilenanzahl mit Hilfe der tMap zu manipulieren: Im ersten Fall wird die Zeilenanzahl nicht manipuliert. Die Sortierung bleibt immer erhalten. Im zweiten Fall ist in der tMap ein Filter definiert und 20 Datensätze werden zurückgehalten. Im dritten Fall sind zwei Ausgänge (output_1 und output_2) definiert. Diese besitzen in diesem Beispiel beide die volle Anzahl an Zeilen, könnten jedoch auch spezifisch gefiltert werden. Im vierten und letzten Fall sind ebenfalls zwei Ausgänge definiert, die jedoch in einem Ausgang zusammengefasst wurden.
Sollen diese beiden Ausgangsströme in einem Ausgangsstrom vereint sein, bietet die tMap die Möglichkeit „joined output tables“ als output zu definieren. Dieser joined output ist im SQL Sinne nicht zu verwechseln mit einem JOIN, sondern entspricht einem UNION ALL. Dieses Feature mag jemanden mit ETL Erfahrung ohne viel Erfahrung mit Talend nicht besonders vorkommen, es ist aber entscheidend, da dies in Talend die einzige Möglichkeit ist, einen geschlossenen Datenfluss-Kreis zu erstellen ohne die Gesamtmenge zwischenzuspeichern.
Kleiner Exkurs geschlossener Kreis: Es ist in Talend nicht möglich wie in IBM Datastage oder Informatica Power Center nach dem Auftrennen des Datenstroms diese auf direktem Wege wieder zu vereinen. Es ist weder möglich per tUnion die Datenströme einfach aneinander anzuhängen, noch per tJoin zu vereinen, siehe unseren Blogbeitrag Talend Self-Join. Innerhalb der tMap Komponente können jedoch beliebig viele Ausgangsströme definiert werden (Aufteilen des Datenstroms), die gleichzeitig mit Hilfe eines joined outputs direkt wieder zusammengeführt werden (im Sinne von UNION ALL).
Tabellen pivotieren
Über die oben vorgestellte joined output table ist es möglich eine Tabelle zu pivotieren beziehungsweise zu normalisieren. Enthält das Schema beispielsweise die zwei Spalten ADRESSE1 und ADRESSE2 und diese Spalten sollen in die einzelne Spalte ADRESSE (jedoch in zwei Zeilen) vereint werden, so muss die tMap verwendet werden: Es werden zwei outputs erstellt: „out_adresse1“ und „out_adresse2 joined with out_adresse1“. Nun muss lediglich noch jeweils eine der Spalten ADRESSE1 beziehungsweise ADRESSE2 mit jeweils einem output verbunden werden. Optional kann ein Filter je output definiert werden, ob eine Zeile ausgegeben wird, falls das Adressfeld nicht gefüllt ist.
Die Komponente tNormalize bietet eine weitere Option einen Datensatz zu normalisieren. Hier müssen jedoch zwangsläufig die zu normalisierenden Spalten in einer Spalte, getrennt mit einem frei wählbaren Separator, definiert sein. Numerische Daten müssten so erst zu einem String zusammengesetzt werden, um sie nach der tNormalize wieder von einem String zurück zu dem ursprünglichen Datentyp konvertieren zu müssen. Da liefert die oben beschriebene Methode mit der tMap die bessere Lösung.
Tabellen joinen
Die tMap kann weiterhin zum Joinen (SQL JOIN) mehrerer Tabellen verwendet werden. Es können beliebig viele lookup rows in die tMap führen, die per cross join, left join oder inner join an den Datenstrom angefügt werden können. Die lookup Datenmenge wird beim Ausführen des Jobs vor dem Start des führenden Datenstroms aufgebaut und im Speicher gehalten. Hier ist also bei großen Datenmengen Vorsicht geboten. Werden in einem Datenstrom mehrere lookup rows aufgebaut, ist eventuell die Option in der tMap interessant alle lookups gleichzeitig aufzubauen. Ansonsten wird sequenziell geladen.
Interessant ist hier die Option an dem tMap Ausgang catch inner join rejects: An einem tMap Ausgang lässt sich die Option aktivieren alle inner join rejects auszugeben. Dies entspricht im SQL Sinne ein
SELECT A.KEY, B.KEY
FROM EMPLOYEE A
LEFT JOIN MANAGER B
ON A.KEY=B.KEY
WHERE B.KEY IS NULL -- get all (inner join) rejects, i.e., all employees
without managers
Diese Option ist zum Beispiel für ein typisches Ende einer ETL Strecke für den insert-Strang in eine Tabelle sinnvoll, in der zuvor geprüft wird, ob es die Datensätze schon im Ziel gibt. Zeitgleich kann in der tMap ein (update-)Ausgang mit den getroffenen Join Zeilen existieren; eine Kombination aus beiden Ausgängen ist über joined output ebenfalls möglich.
Expressions
Die tMap ist horizontal aufgeteilt in drei Bereiche: Links ist Platz für den Haupteingangsstrom und opional für weitere lookup Tabellen. Auf der rechten Seite befinden sich die schon ausführlich beschriebenen Ausgänge. In der Mitte ist jedoch nicht nur Platz für die Darstellung der Verbindungen vom Eingang zum Ausgang, es können weiterhin beliebig viele Variablen definiert werden. Diese Variablen verhalten sich genau so wie die Informatica Komponente Expressions: Pro Zeile im Eingang werden die Variablen “von oben nach unten” geladen. Es gibt drei Hauptanwendungsfälle:
1. Bessere Lesbarkeit und Wartbarkeit, wenn auf expressions im Ausgang verzichtet wird
Selbst kleinste Änderungen an einer Spalte, sei es nur eine Datentypkonvertierung, können zu Problemen führen. Wenn diese Transformation nur in der expression im Ausgang versteckt ist, kann sie leicht übersehen werden. Wenn jedoch in den Variablen explizit zum Beispiel die Spalte column1 in die Variable Var.column1_not_null übergeht und diese dann dem Ausgang übergeben wird, ist die Änderung direkt offensichtlich.
2. Bessere Lesbarkeit und Wartbarkeit bei komplexeren beziehungsweise verschachtelten Expressions
Komplexe Transformationen, die auf mehrere Einzelschritte aufgeteilt werden können, können durch die Verwendung von Variablen besser wartbar implementiert werden. Das naming ist hier entscheidend. Weiterhin können einzelne Variablen in Folgeschritten wiederverwendet werden. Wird beispielsweise input_row.column5 vielfach mit einer Transformation benötigt, ist die Verwendung von
Var.column5_not_null_default
einfacher zu verwenden als beispielsweise an mehrfachen Stellen den etwas sperrigen Ausdruck
(input_row.column5 == null || input_row.column5.equals("") ? "default_saracus_value": input_row.column5)
zu verwenden.
3. Zugang zu der vorangegangenen Zeile, indem auf Variablen zugegriffen wird, die “weiter unten” definiert sind
Durch das Aufrufen von Variablen kann auf die Information der vorangegangenen Zeile zugegriffen werden, da die Variablen nicht bei jeder neuen Zeile erneut initialisiert werden, sondern der Reihe nach neu gesetzt werden. Diese Eigenschaft ist nur dann sinnvoll auszunutzen, wenn die Eingangsdaten sortiert sind und beispielsweise zu jeder Gruppe eine Information gesucht wird, oder beispielsweise bei einer Zeitreihe der Bezug zur vorangegangen Zeile hergestellt wird analog der SQL nativen window-Funktionen lag() oder lead().
Fazit
Die tMap ist der fast-alles-Könner unter den Talend Komponenten. Auch wenn einzelne Aufgaben mit den spezielleren Komponenten wie tJoin, tFilterRow, tFilterColumn, tJavaRow oder tReplicate durchgeführt werden können, greifen viele Entwickler aus Gewohnheit direkt zur tMap. Das bringt vor allem den Vorteil der Flexibilität direkt zwei oder mehr Operationen in einer Komponente wie zum Beispiel “join lookuptable and create insert and update flow” durchzuführen. Diese Anforderung benötigt andernfalls drei oder vier Komponenten. Letztendlich macht die Option joined_output_tables zu erstellen die tMap unabdingbar.
Hat Ihnen dieser Beitrag in unserem saracus Blog gefallen? Dann schreiben Sie uns doch und geben Feedback. Haben Sie einen Wunsch für ein zukünftiges Thema? Geplant ist ein Beitrag zu verschieden Ladestrategien, ein Beitrag wie sich das Sortieren von Daten ausnutzen lässt und ein Beitrag zu Teststrategien.