Hive-Funktionen: Beispiel für integrierte und benutzerdefinierte Funktionen (UDF).

⚡ Intelligente Zusammenfassung

Hive-Funktionen lassen sich in zwei Gruppen einteilen: integrierte Funktionen, die mit der Engine ausgeliefert werden und Sammlungen, Datumsberechnungen, mathematische Operationen, bedingte Operationen, Zeichenkettenverarbeitung und sonstige Aufgaben abdecken, sowie benutzerdefinierte Funktionen, die in Hive geschrieben wurden. Java für Logik liefert Hive keine.

  • 📚 Sechs integrierte Familien: Sammlungs-, Datums-, mathematische, bedingte, Zeichenketten- und sonstige Funktionen können direkt innerhalb von HiveQL aufgerufen werden.
  • 🧾 Unterschriften sind wichtig: Jede Funktion hat eine feste Argumentliste und einen dokumentierten Rückgabetyp; der Rückgabetyp bestimmt, wo sie verwendet werden kann.
  • 🧩 UDF füllt die Lücken: Wenn keine integrierte Funktion existiert, Java Die fehlende Operation wird durch eine Klasse bereitgestellt, die von org.apache.hadoop.hive.ql.exec.UDF erbt.
  • 🔢 Drei Formen der benutzerdefinierten Funktion: UDF gibt für jede Zeile eine Zeile zurück, UDAF fasst mehrere Zeilen zu einer zusammen und UDTF erweitert eine Zeile zu mehreren.
  • Registrierung in zwei Schritten: ADD JAR fügt den Code dem Klassenpfad hinzu und CREATE TEMPORARY FUNCTION bindet einen Namen an die Klasse.
  • ♻️ Wiederverwendung ist der Sinn der Sache: Eine getestete benutzerdefinierte Funktion, wie beispielsweise ein Stemmer, kann von jeder Abfrage aus aufgerufen werden, anstatt sie jedes Mal neu zu schreiben.

Hive-Funktionen: Integrierte und benutzerdefinierte Funktionen

Funktionen werden für einen bestimmten Zweck erstellt, um Operationen wie mathematische, arithmetische, logische und relationale Operationen auf den Operanden von Tabellenspaltennamen durchzuführen.

Eingebaute Funktionen

Dabei handelt es sich um Funktionen, die in Hive bereits verfügbar sind. Zuerst müssen wir die Anwendungsanforderungen prüfen und dann können wir diese integrierten Funktionen in unseren Anwendungen verwenden. Wir können diese Funktionen direkt in unserer Anwendung aufrufen.

Die Syntax und Typen werden im folgenden Abschnitt erwähnt.

Arten von integrierten Funktionen in Hive:

  • Sammlungsfunktionen
  • Datumsfunktionen
  • Mathematische Funktionen
  • Bedingte Funktionen
  • String-Funktionen
  • Sonstiges Funktionen

Im Folgenden werden alle sechs Funktionsfamilien mit ihren Funktionssignaturen und Rückgabetypen beschrieben.

Sammlungsfunktionen

Diese Funktionen werden für Sammlungen verwendet. Sammlungen sind Gruppen von Personen, die sich in einem Netzwerk von Personen aufhalten ... in einemping Sie geben ein einzelnes Element oder ein Array von Elementen zurück, abhängig vom im Funktionsnamen angegebenen Rückgabetyp.

Rückgabetyp Funktionsname Beschreibung
INT Größe (Karte ) Es ruft die Anzahl der Komponenten im Kartentyp ab und gibt sie aus.
INT Größe(Array ) Es ruft die Anzahl der Elemente im Array-Typ ab und gibt sie aus.
Array map_keys(Map ) Es ruft die Schlüssel der Eingabe-Map ab und gibt ein Array zurück, das diese enthält. Das Array ist unsortiert.
Array map_values(Map ) Es ruft die Werte der Eingabe-Map ab und gibt ein Array zurück, das diese Werte enthält. Das Array ist unsortiert.
Array sort_array(Array ) Sortiert das Eingabe-Array in aufsteigender Reihenfolge seiner Elemente und gibt es zurück.
Boolean array_contains(Array , Wert) Gibt TRUE zurück, wenn das Array den als zweites Argument übergebenen Wert enthält.

Datumsfunktionen

Diese werden verwendet, um Datumsmanipulationen und die Konvertierung von Datumstypen von einem Typ in einen anderen durchzuführen:

Funktionsname Rückgabetyp Beschreibung
unix_timestamp() BigInt Wir werden den Strom bekommen Unix Zeitstempel in Sekunden. Der Wert ist nicht für die gesamte Abfrage festgelegt.
to_date(string timestamp) Datum Es ruft den Datumsanteil einer Zeitstempelzeichenfolge ab und gibt ihn aus.
Jahr (String-Datum) INT Es ruft den Jahresteil eines Datums oder einer Zeitstempelzeichenfolge ab und gibt ihn aus
Quartal (Datum/Zeitstempel/Zeichenfolge) INT Es ruft das Quartal des Jahres für ein Datum, einen Zeitstempel oder eine Zeichenfolge im Bereich von 1 bis 4 ab und gibt es aus
Monat (String-Datum) INT Es gibt den Monatsteil eines Datums oder einer Zeitstempelzeichenfolge an
Stunde(String-Datum) INT Es wird die Stunde des Zeitstempels abrufen und ausgeben.
Minute(String-Datum) INT Es ruft die Minute des Zeitstempels ab und gibt sie aus.
date_sub(string Startdatum, int Tage) Datum Es wird das Ergebnis der Unterabfrage abrufen und ausgeben.traceine Anzahl von Tagen ab dem Startdatum
aktuelles_Datum Datum Es wird das aktuelle Datum zu Beginn der Abfrageauswertung abrufen und ausgeben.
last_day(string date) Schnur Es wird den letzten Tag des Monats, zu dem das Datum gehört, abrufen und ausgeben.
trunc(String-Datum, String-Format) Schnur Es ruft das auf die durch das Format angegebene Einheit gekürzte Datum ab und gibt es aus. Unterstützte Formate: MONAT/MON/MM, JAHR/JJJJ/JJ.

Mathematische Funktionen

Diese Funktionen werden für mathematische Operationen verwendet. Anstatt benutzerdefinierte Funktionen (UDFs) zu erstellen, bietet Hive einige integrierte mathematische Funktionen.

Funktionsname Rückgabetyp Beschreibung
rund (DOPPEL-X) DOPPELT Es wird den gerundeten BIGINT-Wert von X abrufen und zurückgeben.
rund (DOUBLE X, INT d) DOPPELT Es wird X auf d Dezimalstellen gerundet abrufen und zurückgeben.
braun (DOPPEL-X) DOPPELT Es wird den gerundeten BIGINT-Wert von X unter Verwendung des HALF_EVEN-Rundungsmodus, auch bekannt als Banker-Rundung, abrufen und zurückgeben.
Boden (DOPPEL-X) GROSSARTIG Es ruft den größten BIGINT-Wert ab und gibt ihn zurück, der gleich oder kleiner als der Wert von X ist.
Decke(DOUBLE a), Decke(DOUBLE a) GROSSARTIG Es ruft den kleinsten BIGINT-Wert ab und gibt ihn zurück, der gleich oder größer als der Wert a ist.
rand(), rand(INT Seed) DOPPELT Es wird eine Zufallszahl abgerufen und zurückgegeben, die gleichverteilt zwischen 0 und 1 liegt. Durch die Angabe eines Startwerts (Seed) wird die Sequenz wiederholbar.

Bedingte Funktionen

Diese Funktionen werden für bedingte Wertprüfungen verwendet.

Funktionsname Rückgabetyp Beschreibung
if(Boolean testCondition, T valueTrue, T valueFalseOrNull) T Es liefert den Wert „true“, wenn die Testbedingung wahr ist, und andernfalls „falseOrNull“.
isnull(X) Boolean Es ruft den Wert ab und gibt true zurück, wenn X NULL ist, und andernfalls false.
isnotnull(X) Boolean Es ruft den Wert ab und gibt true zurück, wenn X nicht NULL ist, und andernfalls false.
nvl(T Wert, T Standardwert) T Es gibt default_value zurück, wenn value NULL ist, und ansonsten value.

String-Funktionen

Die Bearbeitung von Zeichenketten und die Durchführung von Zeichenkettenoperationen erfolgen durch die folgenden Funktionen.

Funktionsname Rückgabetyp Beschreibung
reverse(string X) Schnur Es ergibt sich die umgekehrte Zeichenfolge von X
rpad(string str, int length, string pad) Schnur Es wird str abrufen und rechtsseitig mit pad auf eine Gesamtlänge von Länge auffüllen und zurückgeben.
rtrim(string X) Schnur Es wird die Zeichenkette abrufen und zurückgeben, die durch das Entfernen von Leerzeichen vom Ende (rechten Seite) von X entsteht.
Zum Beispiel, rtrim(' results ') ergibt ' results'
Leerzeichen(INT n) Schnur Es wird eine Zeichenkette aus n Leerzeichen abrufen und ausgeben.
split(STRING str, STRING pat) Array Teilt str um pat auf (pat ist ein regulärer Ausdruck).
str_to_map(text[, delimiter1, delimiter2]) Karte Es teilt den Text mithilfe zweier Trennzeichen in Schlüssel-Wert-Paare auf. Trennzeichen 1 trennt die Paare, und Trennzeichen 2 teilt jedes Paar.

Sonstiges Funktionen

Mehrere integrierte Funktionen gehören keiner der oben genannten Familien an. Dazu gehören Hashing, Sitzungsinformationen und der Aufruf beliebiger Funktionen. Java Methoden.

Funktionsname Rückgabetyp Beschreibung
hash(a1[, a2…]) INT Gibt einen Hashwert der Argumente zurück.
aktueller_Benutzer() Schnur Gibt den aktuellen Benutzernamen des konfigurierten Authentifizierungsmanagers zurück.
aktuelle_Datenbank() Schnur Gibt den Namen der aktuellen Datenbank zurück
md5(Zeichenkette/Binär) Schnur Gibt die MD5-128-Bit-Prüfsumme als 32-stellige Hexadezimalzeichenkette zurück oder NULL für ein NULL-Argument.
sha1(Zeichenkette/Binär) Schnur Gibt den SHA-1-Digest des Arguments als Hexadezimalzeichenkette zurück.
crc32(Zeichenkette/Binär) BigInt Gibt den CRC-Wert eines String- oder Binärarguments zurück.
Ausführung() Schnur Gibt die Hive-Version als Build-Nummer gefolgt von einem Build-Hash zurück.
reflect(class, method[, arg1…]) variiert Ruft einen Java Methode durch Abgleich der Argumentsignatur mittels Reflection. java_method() ist ein Synonym

UDFs (benutzerdefinierte Funktionen)

In Hive können Benutzer eigene Funktionen definieren, um bestimmte Kundenanforderungen zu erfüllen. Diese werden in Hive als benutzerdefinierte Funktionen (UDFs) bezeichnet. Benutzerdefinierte Funktionen werden in folgender Sprache geschrieben: Java für bestimmte Module.

Einige UDFs sind speziell für die Wiederverwendbarkeit von Code in Anwendungsframeworks konzipiert. Der Entwickler schreibt diese Funktionen in Java und integriert diese UDFs in Hive.

Während der Abfrageausführung kann der Entwickler den Code direkt verwenden, und die benutzerdefinierten Funktionen (UDFs) liefern Ergebnisse gemäß den benutzerdefinierten Aufgaben. Dies gewährleistet eine hohe Performance sowohl bei der Codierung als auch bei der Ausführung.

Für das Stemming von Zeichenketten gibt es in Hive beispielsweise keine vordefinierte Funktion. Dafür können wir eine Stem-UDF schreiben. JavaWo immer wir Stammfunktionalität benötigen, können wir diese Stamm-UDF direkt in Hive aufrufen.

Hier bedeutet Stammreduktion, Wörter von ihren Wortstämmen abzuleiten. Ein Stammreduktionsalgorithmus reduziert die Wörter „wishing“, „wished“ und „wishes“ auf den Wortstamm „wish“. Um diese Funktionalität zu implementieren, können wir eine benutzerdefinierte Funktion (UDF) schreiben. Java und integrieren Sie es mit Hive.

Je nach Anwendungsfall kann die UDF so geschrieben werden, dass sie eine unterschiedliche Anzahl von Eingabe- und Ausgabewerten akzeptiert und erzeugt.

Der allgemeine UDF-Typ akzeptiert einen einzelnen Eingabewert und erzeugt einen einzelnen Ausgabewert. Wird der UDF in einer Abfrage verwendet, wird er für jede Zeile im Ergebnisdatensatz einmal aufgerufen.

Umgekehrt kann eine Funktion auch eine Gruppe von Werten als Eingabe akzeptieren und einen einzelnen Ausgabewert zurückgeben. Dieser Unterschied trennt die drei im Folgenden beschriebenen benutzerdefinierten Funktionstypen.

UDF vs UDAF vs UDTF in Hive

Benutzerdefinierte Funktionen in Hive werden danach gruppiert, wie viele Zeilen als Eingabe und wie viele als Ausgabe zurückgegeben werden. Die Wahl des falschen Datentyps ist der häufigste Grund dafür, dass eine benutzerdefinierte Funktion nicht kompiliert werden kann oder nur eine einzelne Zeile zurückgibt, anstatt einer erwarteten Tabelle.

Typ Zeilen rein → Zeilen raus Klasse zum Erweitern Eingebaute Beispiele
UDF Eine Zeile → eine Zeile org.apache.hadoop.hive.ql.exec.UDF Länge(), Runden(), Umkehren()
UDAF Viele Zeilen → eine Zeile org.apache.hadoop.hive.ql.udf.generic.AbstractGenericUDAFResolver Anzahl(), Minimum(), Maximum()
UDTF Eine Zeile → viele Zeilen org.apache.hadoop.hive.ql.udf.generic.GenericUDTF explode(), json_tuple(), parse_url_tuple()

Aus der Tabelle ergeben sich zwei praktische Regeln:

  • Eine UDAF wird fast immer mit einer GROUP BY-Klausel kombiniert, da sie jede Gruppe auf eine einzige Zeile reduziert.
  • Eine UDTF kann nicht zusammen mit anderen Spalten in derselben SELECT-Liste ausgewählt werden, daher wird sie normalerweise mit einer LATERAL VIEW verwendet.

Darüber hinaus gibt es eine zweite, leistungsfähigere Basisklasse für die Arbeit auf Zeilenebene, GenericUDF, die komplexe Typen wie Arrays, Maps und Structs sowie eine variable Anzahl von Argumenten akzeptiert.

Wie man eine UDF in Hive schreibt und registriert

Das oben beschriebene Stammbeispiel lässt sich in vier Schritten als reelle Funktion erstellen. Nichts darüber hinaus. Java Es wird ein Compiler und eine laufende Hive-Sitzung benötigt.

Schritt 1) Schreiben Java Klasse, die UDF erweitert und eine öffentliche evaluate()-Methode implementiert. Hive ruft evaluate() einmal pro Zeile auf, daher muss die Methode auch NULL-Eingaben verarbeiten können.

package com.guru99.hive.udf;

import org.apache.hadoop.hive.ql.exec.UDF;
import org.apache.hadoop.io.Text;

public final class Stem extends UDF {

    public Text evaluate(final Text input) {
        if (input == null) {
            return null;
        }
        String word = input.toString().toLowerCase();
        if (word.endsWith("ing")) {
            word = word.substring(0, word.length() - 3);
        } else if (word.endsWith("ed") || word.endsWith("es")) {
            word = word.substring(0, word.length() - 2);
        }
        return new Text(word);
    }
}

Schritt 2) Kompilieren Sie die Klasse und packen Sie sie in eine JAR-Datei, zum Beispiel hive-udf-1.0.jar, zusammen mit allen Klassen, von denen sie abhängt.

Schritt 3) Fügen Sie die JAR-Datei dem Hive-Classpath hinzu und binden Sie einen Funktionsnamen an die Klasse. Eine temporäre Funktion ist nur für die aktuelle Sitzung gültig.

ADD JAR /home/hduser/hive-udf-1.0.jar;

CREATE TEMPORARY FUNCTION stem AS 'com.guru99.hive.udf.Stem';

Schritt 4) Rufen Sie die neue Funktion genau wie eine integrierte Funktion auf. Angewendet auf die Wörter „wishing“, „wished“ und „wishes“ gibt diese Klasse für alle drei „wish“ zurück.

SELECT word, stem(word) FROM words;

Um die Funktion für jede Sitzung und jeden Benutzer verfügbar zu halten, sollte sie stattdessen dauerhaft in einer Datenbank registriert werden. Die JAR-Datei muss sich in einem Verzeichnis befinden, auf das der gesamte Cluster zugreifen kann, was üblicherweise HDFS bedeutet.

CREATE FUNCTION default.stem AS 'com.guru99.hive.udf.Stem'
USING JAR '/user/hive/udfs/hive-udf-1.0.jar';

Eine einzelne Klasse kann mehrere `evaluate()`-Methoden deklarieren. Hive gleicht den Aufruf mit den Argumentsignaturen ab, wodurch eine Funktion sowohl einen String als auch eine Ganzzahl akzeptieren kann.

Häufig gestellte Fragen

SHOW FUNCTIONS listet alle registrierten Namen auf, einschließlich benutzerdefinierter. DESCRIBE FUNCTION Name gibt eine einzeilige Signatur aus, und DESCRIBE FUNCTION EXTENDED Name fügt Anwendungsbeispiele hinzu, sofern die implementierende Klasse diese bereitstellt.

Fast immer liegt ein Namens- oder Gültigkeitsbereichsproblem vor: Die Zeichenkette nach AS muss der vollqualifizierte Klassenname sein, und ADD JAR gilt nur für die Sitzung, in der es ausgeführt wurde. Beim erneuten Verbinden werden sowohl die JAR-Datei als auch alle temporären Funktionen gelöscht.

Verwenden Sie GenericUDF, wenn die Funktion komplexe Datentypen wie Arrays, Maps oder Strukturen, eine variable Anzahl von Argumenten oder die Validierung der Argumenttypen selbst erfordert. Die einfache UDF-Klasse löst Typen per Reflektion auf und verarbeitet nur primitive Writables.

Eine echte UDF muss auf der JVM ausgeführt werden. Für andere Sprachen gilt Folgendes: Hive bietet die TRANSFORM-Klausel an, die jede Zeile durch ein externes Skript wie z. B. streamt Python über Standard-Ein- und -Ausgabe. Es ist langsamer, vermeidet aber Java vollständig.

Das ist möglich. `evaluate()` wird einmal pro Zeile ausgeführt, wodurch rechenintensive Logik mit der Zeilenanzahl multipliziert wird, und die Objektallokation innerhalb der Methode erhöht den Druck auf die Speicherbereinigung. Verwenden Sie daher nach Möglichkeit eine integrierte Funktion und vermeiden Sie Ein-/Ausgabeoperationen in `evaluate()`.

Nein. Funktionsnamen werden nicht nach Groß- und Kleinschreibung aufgelöst, daher sind ROUND(), Round() und round() dieselbe Funktion. Java Der Klassenname in der AS-Klausel ist eine andere Sache und muss exakt mit der kompilierten Klasse, einschließlich ihres Pakets, übereinstimmen.

Assistenten für maschinelles Lernen ordnen einer Beschreibung in einfacher Sprache Kandidatensignaturen zu und warnen, wenn ein Rückgabetyp nicht zur Zielspalte passt. Überprüfen Sie den Vorschlag anhand der dokumentierten Signatur, da generierte Namen manchmal einem anderen SQL-Dialekt angehören.

Es erzeugt aus einem Kommentar, der die Operation beschreibt, ein nutzbares Grundgerüst – die Klassendeklaration, Importe und eine `evaluate()`-Methode. Die Behandlung von Nullwerten, beschreibbare Typen und der Paketierungsschritt müssen noch überprüft werden, und die Funktion muss mit echten Datensätzen getestet werden.

Fassen Sie diesen Beitrag mit folgenden Worten zusammen: