Funcții Hive: Exemplu încorporate și UDF (definite de utilizator)

⚡ Rezumat inteligent

Funcțiile Hive se împart în două grupuri: funcții încorporate livrate odată cu motorul și care acoperă colecții, date, matematice, condiționale, șiruri de caractere și diverse, și funcții definite de utilizator scrise în Java căci logica Hive nu furnizează.

  • 📚 Șase familii încorporate: Funcțiile de colecție, de dată, matematice, condiționale, de șir de caractere și diverse pot fi apelate direct în HiveQL.
  • 🧾 Semnăturile contează: Fiecare funcție are o listă de argumente fixă ​​și un tip de retur documentat, astfel încât tipul de retur decide unde poate fi utilizat.
  • 🧩 UDF umple golurile: Când nu există nicio funcție încorporată, o Java Clasa care extinde org.apache.hadoop.hive.ql.exec.UDF furnizează operația lipsă.
  • 🔢 Trei forme de funcții personalizate: UDF returnează câte un rând per rând, UDAF restrânge mai multe rânduri într-unul singur, iar UDTF extinde un rând în mai multe.
  • 🛠️ Înregistrare în doi pași: ADD JAR plasează codul pe calea clasei, iar CREATE TEMPORARY FUNCTION leagă un nume de clasă.
  • ♻️ Reutilizarea este ideea: O UDF testată, cum ar fi un stemmer, poate fi apelată din fiecare interogare în loc să fie rescrisă de fiecare dată.

Funcții Hive: Funcții încorporate și definite de utilizator

Funcțiile sunt construite cu un scop specific, pentru a efectua operații precum operații matematice, aritmetice, logice și relaționale asupra operanzilor numelor coloanelor din tabel.

Funcții încorporate

Acestea sunt funcții care sunt deja disponibile în Hive. În primul rând, trebuie să verificăm cerințele aplicației și apoi putem folosi aceste funcții încorporate în aplicațiile noastre. Putem apela aceste funcții direct în aplicația noastră.

Sintaxa și tipurile sunt menționate în secțiunea următoare.

Tipuri de funcții încorporate în Hive:

  • Funcții de colectare
  • Funcții de dată
  • Funcții matematice
  • Funcții condiționate
  • Funcții șiruri
  • Diverse Funcții

Fiecare dintre cele șase familii este prezentată mai jos, împreună cu semnăturile sale de funcții și tipurile de returnare.

Funcții de colectare

Aceste funcții sunt folosite pentru colecții. Colecțiile înseamnă grupulping de elemente și returnează un singur element sau o matrice de elemente, în funcție de tipul de returnare menționat în numele funcției.

Tipul de returnare Numele funcției Descriere
INT dimensiune (Hartă ) Va prelua și va da numărul de componente din tipul de hartă
INT dimensiune (Matrice ) Va prelua și va da numărul de elemente din tipul de matrice
Matrice map_keys(Hartă ) Va prelua și va oferi un array care conține cheile hărții de intrare. Array-ul este neordonat.
Matrice map_values(Hartă ) Va prelua și va afișa un tablou care conține valorile hărții de intrare. Tabloul este neordonat.
Matrice sortare_matrice(Matrice ) Sortează matricea de intrare în ordinea crescătoare a elementelor sale și o returnează
boolean array_contains(Array , valoare) Returnează TRUE dacă matricea conține valoarea transmisă ca al doilea argument.

Funcții de dată

Acestea sunt folosite pentru a efectua manipulări de date și conversia tipurilor de date de la un tip la altul:

Numele funcției Tipul de returnare Descriere
unix_timestamp() BIGINT Vom obține curentul Unix marcaj temporal în secunde. Valoarea nu este fixă ​​pentru întreaga interogare
până_dată(șir de caractere timestamp) data Va prelua și va oferi partea de dată a unui șir de timestamp
an (data sirului) INT Acesta va prelua și va oferi partea anului dintr-o dată sau un șir de marcaj temporal
trimestru (data/timestamp/șir) INT Acesta va prelua și va oferi trimestrul anului pentru o dată, un marcaj de timp sau un șir în intervalul de la 1 la 4
luna(data sirului) INT Va da partea de lună a unei date sau a unui șir de marcaj temporal
ora (data sirului) INT Va prelua și va afișa ora marcajului temporal
minut(data sirului) INT Va prelua și va oferi minutul marcajului temporal
date_sub(șir data de începere, int zile) data Va prelua și va da rezultatul subtracla un număr de zile de la data de începere
data_actuală data Va prelua și va afișa data curentă la începutul evaluării interogării
ultima_zi(șir dată) şir Va prelua și va afișa ultima zi a lunii căreia îi aparține data.
trunc (data șir, format șir) şir Va prelua și va afișa data trunchiată la unitatea specificată de format. Formate acceptate: LUNA/LU/LL, AN/AAAA/AA.

Funcții matematice

Aceste funcții sunt folosite pentru operații matematice. În loc să creăm UDF-uri, avem câteva funcții matematice încorporate în Hive.

Numele funcției Tipul de returnare Descriere
rotund(DUBLU X) DUBLA Va prelua și returna valoarea BIGINT rotunjită a lui X.
rotund(DUBLU X, INT d) DUBLA Va prelua și returna X rotunjit la d zecimale
rotund(DUBLU X) DUBLA Va prelua și returna valoarea BIGINT rotunjită a lui X folosind modul de rotunjire HALF_EVEN, cunoscut și sub numele de rotunjire a bancherilor.
podea (DUBLU X) BIGINT Va prelua și returna valoarea maximă BIGINT care este egală sau mai mică decât valoarea X.
plafon (DUBLU a), plafon (DUBLU a) BIGINT Va prelua și returna valoarea minimă BIGINT care este egală sau mai mare decât valoarea a.
rand(), rand (sămânță INT) DUBLA Va prelua și returna un număr aleator distribuit uniform de la 0 la 1. Furnizarea unei valori inițiale face ca secvența să fie repetabilă.

Funcții condiționate

Aceste funcții sunt utilizate pentru verificări condiționale ale valorilor.

Numele funcției Tipul de returnare Descriere
if(Boolean testCondition, T valueTrue, T valueFalseOrNull) T Va da valueTrue când testCondition este true și valueFalseOrNull în caz contrar.
este nul(X) boolean Va prelua și va da valoarea „true” dacă X este NULL și „false” în caz contrar.
nu este nul(X) boolean Va prelua și va da valoarea „true” dacă X nu este NULL și „false” în caz contrar.
nvl(valoare T, valoare_implicită T) T Va da valoarea_implicită când valoarea este NULL și valoarea în caz contrar.

Funcții șiruri

Manipulările și operațiile cu șiruri de caractere sunt gestionate de următoarele funcții.

Numele funcției Tipul de returnare Descriere
inversă(șir X) şir Va da șirul inversat al lui X
rpad(string str, int lungime, string pad) şir Va prelua și va da str right-padded cu pad până la o lungime totală de length
rtrim(șir X) şir Va prelua și returna șirul rezultat din eliminarea spațiilor de la capătul (partea dreaptă) a lui X.
De exemplu, rtrim('rezultate') rezultă în 'rezultate'
spațiu(INT n) şir Va prelua și va oferi un șir de n spații.
împărțit(STRING str, STRING pat) mulțime Împarte str în jurul pat (pat este o expresie regulată).
str_to_map(text[, delimitator1, delimitator2]) hartă Va împărți textul în perechi cheie-valoare folosind doi delimitatori. Delimiter1 separă perechile, iar delimiter2 împarte fiecare pereche.

Diverse Funcții

Mai multe funcții încorporate nu aparțin niciuneia dintre familiile de mai sus. Acestea acoperă hashing-ul, informațiile de sesiune și apelarea arbitrară. Java metode.

Numele funcției Tipul de returnare Descriere
hash(a1[, a2…]) INT Returnează o valoare hash a argumentelor
utilizator_current() şir Returnează numele de utilizator curent din managerul de autentificare configurat
baza_de_date_curentă() şir Returnează numele bazei de date curente
md5(șir/binar) şir Returnează suma de control MD5 pe 128 de biți ca șir de 32 de cifre hexadecimale sau NULL pentru un argument NULL
sha1(șir/binar) şir Returnează digestul SHA-1 al argumentului ca șir hexadecimal
crc32(șir/binar) BIGINT Returnează valoarea verificării redundanței ciclice a unui șir de caractere sau a unui argument binar
versiune() şir Returnează versiunea Hive ca număr de compilare urmat de un hash de compilare
reflectă(clasă, metodă[, arg1…]) variază Apelează la Java metodă prin potrivirea semnăturii argumentului, folosind reflecția. java_method() este un sinonim

UDF-uri (funcții definite de utilizator)

În Hive, utilizatorii își pot defini propriile funcții pentru a îndeplini anumite cerințe ale clientului. Acestea sunt cunoscute sub numele de UDF-uri în Hive. Funcțiile definite de utilizator sunt scrise în Java pentru module specifice.

Unele UDF-uri sunt special concepute pentru reutilizarea codului în framework-urile de aplicații. Dezvoltatorul scrie aceste funcții în Java și integrează acele UDF-uri cu Hive.

În timpul execuției interogării, dezvoltatorul poate utiliza direct codul, iar UDF-urile vor returna ieșiri conform sarcinilor definite de utilizator. Aceasta oferă performanțe ridicate în ceea ce privește codarea și execuția.

De exemplu, pentru utilizarea stemming a șirurilor de caractere nu avem nicio funcție predefinită în Hive. Pentru aceasta, putem scrie o UDF stem în JavaOriunde avem nevoie de funcționalitate stem, putem apela direct această UDF stem în Hive.

Aici, funcționalitatea radicală înseamnă derivarea cuvintelor din rădăcinile lor. Un algoritm de derivare a radicalilor reduce cuvintele „wishing”, „wished” și „wishes” la rădăcina cuvântului „wish”. Pentru a efectua acest tip de funcționalitate, putem scrie o UDF în Java și să-l integreze cu Stup.

În funcție de cazul de utilizare, UDF-ul poate fi scris pentru a accepta și produce un număr diferit de valori de intrare și ieșire.

Tipul general de UDF va accepta o singură valoare de intrare și va produce o singură valoare de ieșire. Dacă UDF-ul este utilizat într-o interogare, atunci UDF-ul va fi apelat o dată pentru fiecare rând din setul de date rezultat.

În cealaltă direcție, o funcție poate accepta un grup de valori ca intrare și poate returna o singură valoare de ieșire. Această diferență este ceea ce separă cele trei tipuri de funcții personalizate descrise în continuare.

UDF vs UDAF vs UDTF în Hive

Funcțiile personalizate din Hive sunt grupate în funcție de numărul de rânduri introduse și de câte ies. Alegerea tipului greșit este cel mai frecvent motiv pentru care o funcție personalizată refuză să compileze sau returnează un singur rând acolo unde era așteptat un tabel.

Tip Rânduri de intrare → rânduri de ieșire Clasa de extins Exemple încorporate
UDF Un rând → un rând org.apache.hadoop.hive.ql.exec.UDF lungime(), rotund(), invers()
UDAF Mai multe rânduri → un rând org.apache.hadoop.hive.ql.udf.generic.AbstracRezolvator tGenericUDAF număr(), min(), max()
UDTF Un rând → mai multe rânduri org.apache.hadoop.hive.ql.udf.generic.GenericUDTF explode(), json_tuple(), parse_url_tuple()

Două reguli practice rezultă din tabel:

  • O clauză UDAF este aproape întotdeauna asociată cu o clauză GROUP BY, deoarece restrânge fiecare grup la un singur rând.
  • Un UDTF nu poate fi selectat alături de alte coloane din aceeași listă SELECT, așa că este utilizat în mod normal cu o vedere LATERALĂ.

Există, de asemenea, o a doua clasă de bază, mai capabilă pentru lucrul la nivel de rând, GenericUDF, care acceptă tipuri complexe, cum ar fi tablouri, hărți și structuri, și un număr variabil de argumente.

Cum se scrie și se înregistrează o UDF în Hive

Exemplul de tulpină descris mai sus poate fi construit ca o funcție reală în patru pași. Nimic dincolo de un Java este necesar un compilator și o sesiune Hive care rulează.

Pas 1) Scrie o Java o clasă care extinde UDF-ul și implementează o metodă publică evaluate(). Hive apelează evaluate() o dată pe rând, deci metoda trebuie să gestioneze o intrare 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);
    }
}

Pas 2) Compilați clasa și împachetați-o într-un fișier JAR, de exemplu hive-udf-1.0.jar, împreună cu orice clase de care depinde.

Pas 3) Puneți fișierul JAR pe calea de clasă Hive și legați un nume de funcție de clasă. O funcție temporară este valabilă doar pentru sesiunea curentă.

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

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

Pas 4) Apelează noua funcție exact ca una predefinită. Aplicată cuvintelor „wishing”, „wished” și „wishes”, această clasă returnează „wish” pentru toate trei.

SELECT word, stem(word) FROM words;

Pentru a menține funcția disponibilă fiecărei sesiuni și fiecărui utilizator, înregistrați-o permanent într-o bază de date. Fișierul JAR trebuie să se afle pe o cale pe care întregul cluster o poate citi, ceea ce înseamnă în mod normal HDFS.

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

O singură clasă poate declara mai multe metode evaluate(). Hive compară apelul cu semnăturile argumentelor, acesta fiind modul în care o funcție poate accepta atât un șir de caractere, cât și un număr întreg.

Întrebări frecvente

SHOW FUNCTIONS listează toate numele înregistrate, inclusiv cele personalizate. DESCRIBE FUNCTION nume afișează o semnătură pe o singură linie, iar DESCRIBE FUNCTION EXTENDED nume adaugă exemple de utilizare acolo unde clasa de implementare le furnizează.

Aproape întotdeauna o problemă de nume sau domeniu de aplicare: șirul de după AS trebuie să fie numele complet calificat al clasei, iar ADD JAR se aplică doar sesiunii care l-a rulat. Reconectarea elimină atât JAR-ul, cât și orice funcție temporară.

Folosește GenericUDF atunci când funcția acceptă tipuri complexe, cum ar fi tablouri, hărți sau structuri, un număr variabil de argumente sau trebuie să valideze singură tipurile de argumente. Clasa UDF simplă rezolvă tipurile prin reflecție și gestionează doar elementele Writable primitive.

O UDF adevărată trebuie să ruleze pe JVM. Pentru alte limbaje, Stup oferă clauza TRANSFORM, care transmite fiecare rând printr-un script extern, cum ar fi Python peste intrarea și ieșirea standard. Este mai lent, dar evită Java în întregime.

Acestea pot. evaluate() rulează o dată pe rând, astfel încât logica costisitoare este înmulțită cu numărul de rânduri, iar alocarea obiectelor în cadrul metodei adaugă presiune la colectarea gunoiului. Preferați o funcție încorporată atunci când există una și păstrați evaluate() fără I/O.

Nu. Numele funcțiilor sunt rezolvate fără a ține cont de majuscule/minuscule, deci ROUND(), Round() și round() sunt aceeași funcție. Java Numele clasei din clauza AS este o chestiune diferită și trebuie să corespundă exact cu clasa compilată, inclusiv pachetul său.

Asistenții de învățare automată mapează o descriere în limbaj simplu pe semnăturile candidate și avertizează atunci când un tip de returnare nu se potrivește coloanei țintă. Verificați sugestia în raport cu semnătura documentată, deoarece numele generate aparțin uneori unui alt dialect SQL.

Produce un schelet utilizabil — declarația clasei, importurile și o metodă evaluate() — dintr-un comentariu care descrie operațiunea. Gestionarea valorilor nule, tipurile inscriptibile și pasul de împachetare trebuie încă revizuite, iar funcția trebuie testată pe rânduri reale.

Rezumați această postare cu: