Funkcje Hive: przykład wbudowany i UDF (zdefiniowany przez użytkownika)

⚡ Inteligentne podsumowanie

Funkcje Hive dzielą się na dwie grupy: wbudowane funkcje dostarczane z silnikiem, obejmujące zbiory, daty, obliczenia matematyczne, funkcje warunkowe, ciągi znaków i inne, a także funkcje zdefiniowane przez użytkownika, napisane w Java ponieważ Hive nie dostarcza logiki.

  • 📚 Sześć wbudowanych rodzin: Funkcje kolekcji, daty, matematyczne, warunkowe, łańcuchowe i różne można wywoływać bezpośrednio w HiveQL.
  • 🧾 Podpisy mają znaczenie: Każda funkcja ma ustaloną listę argumentów i udokumentowany typ zwracany, więc typ zwracany decyduje, gdzie można ją wykorzystać.
  • 🧩 UDF wypełnia luki: Jeśli nie istnieje żadna wbudowana funkcja, Java Klasa rozszerzająca org.apache.hadoop.hive.ql.exec.UDF udostępnia brakującą operację.
  • 🔢 Trzy kształty funkcji niestandardowych: Funkcja UDF zwraca jeden wiersz na wiersz, funkcja UDAF łączy wiele wierszy w jeden, a funkcja UDTF rozszerza jeden wiersz na wiele.
  • 🛠️. Rejestracja w dwóch krokach: Polecenie ADD JAR umieszcza kod w ścieżce klasy, a polecenie CREATE TEMPORARY FUNCTION wiąże nazwę z klasą.
  • ♻️ Ponowne wykorzystanie jest najważniejsze: Można wywołać jedną przetestowaną funkcję UDF, np. algorytm naprowadzania, przy każdym zapytaniu zamiast przepisywać ją za każdym razem.

Funkcje Hive: funkcje wbudowane i zdefiniowane przez użytkownika

Funkcje są budowane w określonym celu, aby wykonywać operacje matematyczne, arytmetyczne, logiczne i relacyjne na operandach nazw kolumn tabeli.

Wbudowane funkcje

Są to funkcje, które są już dostępne w Hive. Najpierw musimy sprawdzić wymagania aplikacji, a następnie możemy wykorzystać te wbudowane funkcje w naszych aplikacjach. Funkcje te możemy wywołać bezpośrednio w naszej aplikacji.

Składnia i typy są opisane w następnej sekcji.

Typy wbudowanych funkcji w Hive:

  • Funkcje kolekcji
  • Funkcje daty
  • Funkcje matematyczne
  • Funkcje warunkowe
  • Funkcje łańcuchowe
  • Różne Funkcje

Każda z sześciu rodzin została omówiona poniżej wraz z sygnaturami funkcji i typami zwracanymi.

Funkcje kolekcji

Funkcje te służą do kolekcji. Kolekcje oznaczają grupęping elementów i zwracają pojedynczy element lub tablicę elementów, w zależności od typu zwracanego podanego w nazwie funkcji.

Typ zwrotu Nazwa funkcji OPIS
INT rozmiar (mapa ) Pobiera i podaje liczbę komponentów w typie mapy
INT rozmiar (tablica ) Pobiera i podaje liczbę elementów w typie tablicy
Szyk map_keys(Mapa ) Pobiera i zwraca tablicę zawierającą klucze mapy wejściowej. Tablica jest nieuporządkowana.
Szyk wartości_mapy(mapa ) Pobiera i zwraca tablicę zawierającą wartości mapy wejściowej. Tablica jest nieuporządkowana.
Szyk sort_array(tablica ) Sortuje tablicę wejściową w kolejności rosnącej według jej elementów i zwraca ją
Boolean array_contains(tablica , wartość) Zwraca wartość TRUE, jeśli tablica zawiera wartość przekazaną jako drugi argument

Funkcje daty

Służą one do manipulowania datami i konwersji typów dat z jednego typu na inny:

Nazwa funkcji Typ zwrotu OPIS
unix_timestamp() BigInt Otrzymamy aktualny Unix znacznik czasu w sekundach. Wartość nie jest stała dla całego zapytania.
to_date(znacznik czasu ciągu) dane Pobierze i przekaże część daty z ciągu znacznika czasu
rok (data ciągu) INT Pobierze i poda rok jako część daty lub ciągu znaków czasu
kwartał (data/znacznik czasu/ciąg znaków) INT Pobierze i poda kwartał roku dla daty, znacznika czasu lub ciągu znaków z zakresu od 1 do 4
miesiąc (data ciągu) INT Da miesiącowi część daty lub ciąg znacznika czasu
godzina (data ciągu) INT Pobierze i poda godzinę znacznika czasu
minuta (data ciągu) INT Pobierze i poda minutę znacznika czasu
date_sub(string data początkowa, int dni) dane Pobierze i poda wynik podprogramutracod określonej liczby dni od daty rozpoczęcia
bieżąca_data dane Na początku oceny zapytania zostanie pobrana i podana aktualna data
last_day(ciąg znaków data) ciąg Pobierze i poda ostatni dzień miesiąca, do którego należy dana data
trunc (data ciągu, format ciągu) ciąg Pobierze i zwróci datę skróconą do jednostki określonej w formacie. Obsługiwane formaty: MIESIĄC/MIESIĄC/MM, ROK/RRRR/RR.

Funkcje matematyczne

Te funkcje służą do operacji matematycznych. Zamiast tworzyć funkcje UDF, mamy wbudowane funkcje matematyczne w Hive.

Nazwa funkcji Typ zwrotu OPIS
okrągły (podwójny X) PODWÓJNIE Pobierze i zwróci zaokrągloną wartość BIGINT dla X
zaokrąglenie(DOUBLE X, INT d) PODWÓJNIE Pobierze i zwróci X zaokrąglone do d miejsc dziesiętnych
brązowy(PODWÓJNY X) PODWÓJNIE Pobiera i zwraca zaokrągloną wartość BIGINT X, używając trybu zaokrąglania HALF_EVEN, znanego również jako zaokrąglanie bankierskie
podłoga (podwójne X) DUŻE Pobiera i zwraca maksymalną wartość BIGINT równą lub mniejszą od wartości X
sufit(DOUBLE a), sufit(DOUBLE a) DUŻE Pobiera i zwraca minimalną wartość BIGINT równą lub większą od wartości a
rand(), rand(nasiono INT) PODWÓJNIE Pobiera i zwraca liczbę losową, która jest równomiernie rozłożona od 0 do 1. Podanie ziarna sprawia, że ​​sekwencja jest powtarzalna

Funkcje warunkowe

Funkcje te służą do sprawdzania wartości warunkowych.

Nazwa funkcji Typ zwrotu OPIS
if(Warunek testowy boolowski, wartość T prawda, wartość T fałsz lub null) T Zwróci valueTrue, gdy testCondition jest prawdziwy, a valueFalseOrNull w przeciwnym wypadku.
isnull(X) Boolean Pobierze i zwróci wartość true, jeśli X jest NULL, a false, jeśli nie jest.
isnotnull(X) Boolean Pobierze i zwróci wartość true, jeśli X nie jest NULL, a false, jeśli nie jest.
nvl(wartość T, wartość_domyślna T) T Zwróci wartość domyślną, gdy value jest równe NULL, a value w przeciwnym wypadku.

Funkcje łańcuchowe

Operacje na ciągach znaków i manipulacje na ciągach znaków są obsługiwane za pomocą następujących funkcji.

Nazwa funkcji Typ zwrotu OPIS
odwróć(ciąg X) ciąg Da to odwrócony ciąg znaków X
rpad(str, int długość, string pad) ciąg Pobierze i przekaże ciąg wypełniony z prawej strony z wypełnieniem o całkowitej długości
rtrim(ciąg X) ciąg Pobierze i zwróci ciąg znaków powstały po przycięciu spacji z końca (prawej strony) X.
Na przykład, rtrim('wyniki') daje w wyniku 'wyniki'
spacja(INT n) ciąg Pobierze i zwróci ciąg n spacji.
split(STRING str., STRING pat) szyk Dzieli str wokół pat (pat jest wyrażeniem regularnym).
str_to_map(tekst[, ogranicznik1, ogranicznik2]) mapa Podzieli tekst na pary klucz-wartość za pomocą dwóch ograniczników. Ogranicznik 1 rozdziela pary, a ogranicznik 2 rozdziela każdą parę.

Różne Funkcje

Kilka wbudowanych funkcji nie należy do żadnej z powyższych rodzin. Obejmują one haszowanie, informacje o sesji i wywoływanie dowolnych Java Metody.

Nazwa funkcji Typ zwrotu OPIS
hash(a1[, a2…]) INT Zwraca wartość skrótu argumentów
bieżący_użytkownik() ciąg Zwraca bieżącą nazwę użytkownika z skonfigurowanego menedżera uwierzytelniania
bieżąca_baza_danych() ciąg Zwraca nazwę bieżącej bazy danych
md5(ciąg/binarny) ciąg Zwraca 128-bitową sumę kontrolną MD5 jako ciąg 32 cyfr szesnastkowych lub NULL w przypadku argumentu NULL
sha1(ciąg/binarny) ciąg Zwraca skrót SHA-1 argumentu jako ciąg szesnastkowy
crc32(ciąg/binarny) BigInt Zwraca wartość kontroli redundancji cyklicznej argumentu ciągu lub argumentu binarnego
wersja() ciąg Zwraca wersję Hive jako numer kompilacji, po którym następuje skrót kompilacji
odbij(klasa, metoda[, arg1…]) waha Nazywa się Java metodę poprzez dopasowanie sygnatury argumentu, używając refleksji. java_method() jest synonimem

UDF (funkcje zdefiniowane przez użytkownika)

W Hive użytkownicy mogą definiować własne funkcje, aby spełnić określone wymagania klienta. W Hive są one znane jako funkcje definiowane przez użytkownika (UDF). Funkcje definiowane przez użytkownika są pisane w Java dla konkretnych modułów.

Niektóre funkcje UDF są zaprojektowane specjalnie z myślą o możliwości ponownego wykorzystania kodu w frameworkach aplikacji. Programista pisze te funkcje w Java i integruje te UDF-y z Hive.

Podczas wykonywania zapytania programista może bezpośrednio korzystać z kodu, a funkcje UDF zwracają wyniki zgodnie z zadaniami zdefiniowanymi przez użytkownika. Zapewnia to wysoką wydajność kodowania i wykonywania.

Na przykład, w przypadku stemmingu ciągów znaków nie mamy żadnej predefiniowanej funkcji w Hive. W tym celu możemy napisać funkcję UDF stem w Java. Jeśli potrzebujemy funkcjonalności macierzystej, możemy bezpośrednio wywołać tę funkcję UDF macierzystą w Hive.

W tym przypadku funkcjonalność rdzenia oznacza wyprowadzanie słów z ich rdzeni. Algorytm rdzeniowania redukuje słowa „życzenie”, „chciał” i „życzenia” do rdzenia „życzenie”. Aby wykonać ten typ funkcjonalności, możemy napisać funkcję UDF w Java i zintegrować go z Ul.

W zależności od przypadku użycia funkcja UDF może być napisana tak, aby akceptowała i generowała różną liczbę wartości wejściowych i wyjściowych.

Ogólny typ funkcji UDF akceptuje pojedynczą wartość wejściową i generuje pojedynczą wartość wyjściową. Jeśli funkcja UDF jest używana w zapytaniu, zostanie wywołana jednokrotnie dla każdego wiersza w zestawie danych wynikowych.

Z drugiej strony, funkcja może przyjąć grupę wartości jako dane wejściowe i zwrócić pojedynczą wartość wyjściową. Ta różnica oddziela trzy typy funkcji niestandardowych opisane poniżej.

UDF vs UDAF vs UDTF w Hive

Funkcje niestandardowe w Hive są grupowane według liczby wierszy przychodzących i wychodzących. Wybór niewłaściwego typu to najczęstszy powód, dla którego funkcja niestandardowa odmawia kompilacji lub zwraca pojedynczy wiersz w miejscu, w którym oczekiwano tabeli.

Typ Wiersze w → rzędy na zewnątrz Klasa do rozszerzenia Wbudowane przykłady
UDF Jeden rząd → jeden rząd org.apache.hadoop.hive.ql.exec.UDF długość(), zaokrąglenie(), odwrócenie()
UDAF Wiele rzędów → jeden rząd org.apache.hadoop.hive.ql.udf.generic.AbstractGenericUDAFResolver liczba(), min(), max()
UDTF Jeden wiersz → wiele wierszy org.apache.hadoop.hive.ql.udf.generic.GenericUDTF eksploduj(), json_tuple(), parse_url_tuple()

Z tabeli wynikają dwie praktyczne zasady:

  • Klauzula UDAF jest prawie zawsze łączona z klauzulą ​​GROUP BY, ponieważ powoduje ona skrócenie każdej grupy do jednego wiersza.
  • Kolumny UDTF nie można wybrać obok innych kolumn na tej samej liście SELECT, dlatego zwykle używa się jej z WIDOKIEM BOCZNYM.

Istnieje również druga, bardziej wydajna klasa bazowa do pracy na poziomie wierszy, GenericUDF, która akceptuje złożone typy, takie jak tablice, mapy i struktury, a także zmienną liczbę argumentów.

Jak napisać i zarejestrować UDF w Hive

Opisany powyżej przykład macierzy można zbudować jako funkcję rzeczywistą w czterech krokach. Nic poza Java Wymagany jest kompilator i działająca sesja Hive.

Krok 1) Napisać Java Klasa rozszerzająca UDF i implementująca publiczną metodę evaluate(). Hive wywołuje metodę evaluate() raz dla każdego wiersza, więc metoda musi obsługiwać wartość NULL.

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);
    }
}

Krok 2) Skompiluj klasę i spakuj ją do pliku JAR, na przykład hive-udf-1.0.jar, razem ze wszystkimi klasami, od których jest zależna.

Krok 3) Umieść plik JAR w ścieżce klas Hive i powiąż nazwę funkcji z klasą. Funkcja tymczasowa istnieje tylko w bieżącej sesji.

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

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

Krok 4) Wywołaj nową funkcję dokładnie tak, jak funkcję wbudowaną. Zastosowana do słów „wishing”, „wished” i „wishes”, ta klasa zwróci „wish” dla wszystkich trzech.

SELECT word, stem(word) FROM words;

Aby funkcja była dostępna dla każdej sesji i każdego użytkownika, należy zarejestrować ją na stałe w bazie danych. Plik JAR musi znajdować się na ścieżce, którą może odczytać cały klaster, co zazwyczaj oznacza HDFS.

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

Pojedyncza klasa może deklarować więcej niż jedną metodę evaluate(). Hive dopasowuje wywołanie do sygnatur argumentów, dzięki czemu jedna funkcja może akceptować zarówno ciąg znaków, jak i liczbę całkowitą.

FAQ

SHOW FUNCTIONS wyświetla wszystkie zarejestrowane nazwy, w tym niestandardowe. DESCRIBE FUNCTION name drukuje jednowierszowy podpis, a DESCRIBE FUNCTION EXTENDED name dodaje przykłady użycia, jeśli klasa implementująca je dostarcza.

Prawie zawsze problem dotyczy nazwy lub zakresu: ciąg znaków po AS musi być w pełni kwalifikowaną nazwą klasy, a polecenie ADD JAR dotyczy tylko sesji, w której zostało uruchomione. Ponowne połączenie powoduje usunięcie zarówno pliku JAR, jak i wszelkich funkcji tymczasowych.

Użyj GenericUDF, gdy funkcja przyjmuje typy złożone, takie jak tablice, mapy lub struktury, zmienną liczbę argumentów lub musi samodzielnie zweryfikować typy argumentów. Prosta klasa UDF rozstrzyga typy poprzez refleksję i obsługuje tylko prymitywne obiekty Writable.

Prawdziwy UDF musi działać na JVM. W przypadku innych języków Ul oferuje klauzulę TRANSFORM, która przesyła każdy wiersz przez zewnętrzny skrypt, taki jak Python przez standardowe wejście i wyjście. Jest wolniejszy, ale unika Java całkowicie.

Mogą. Funkcja evaluate() uruchamia się raz na wiersz, więc kosztowna logika jest mnożona przez liczbę wierszy, a alokacja obiektów w metodzie zwiększa obciążenie związane z odśmiecaniem pamięci. Preferuj wbudowaną funkcję, jeśli taka istnieje, i nie wprowadzaj żadnych zmian w funkcji evaluate().

Nie. Nazwy funkcji nie uwzględniają wielkości liter, więc ROUND(), Round() i round() to ta sama funkcja. Java nazwa klasy w klauzuli AS to inna kwestia i musi dokładnie odpowiadać skompilowanej klasie, łącznie z jej pakietem.

Asystenci uczenia maszynowego mapują opis w języku potocznym na sygnatury kandydatów i ostrzegają, gdy typ zwracany nie pasuje do kolumny docelowej. Należy zweryfikować sugestię z udokumentowaną sygnaturą, ponieważ wygenerowane nazwy czasami należą do innego dialektu SQL.

Generuje użyteczny szkielet – deklarację klasy, importy i metodę evaluate() – na podstawie komentarza opisującego operację. Obsługa wartości null, typy zapisywalne i etap pakowania nadal wymagają przeglądu, a funkcja musi zostać przetestowana na rzeczywistych wierszach.

Podsumuj ten post następująco: