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.
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ą.

