Apache Pig UDF: Część 1 - Funkcje oceny, agregacji i filtrowania



Ten post zawiera opis funkcji Apache Pig UDF - Eval, Aggregate & Filter Functions. Spójrz na funkcje Eval, Aggregate i Filter.

Porównanie soli anjbla kucharza lalek

Apache Pig zapewnia szerokie wsparcie dla funkcji zdefiniowanych przez użytkownika (UDF) jako sposób na określenie niestandardowego przetwarzania. Obecnie UDF dla świń można wykonywać w trzech językach: Java, Python, JavaScript i Ruby. Najbardziej rozbudowane wsparcie jest dostępne dla funkcji Java.





Funkcje Java UDF można wywołać na wiele sposobów. Najprostszy UDF może po prostu rozszerzyć EvalFunc, który do zaimplementowania wymaga tylko funkcji exec. Każdy Eval UDF musi to wdrażać. Ponadto, jeśli funkcja jest algebraiczna, może zaimplementować interfejs algebraiczny, aby znacznie poprawić wydajność zapytań.

Znaczenie UDF u świń:

Pig umożliwia użytkownikom łączenie istniejących operatorów z własnym lub cudzym kodem za pośrednictwem UDF. Zaletą Pig jest możliwość umożliwienia użytkownikom łączenia jej operatorów z własnym lub cudzym kodem za pośrednictwem UDF. Aż do wersji 0.7 wszystkie UDF muszą być napisane w Javie i zaimplementowane jako klasy Java. Ułatwia to dodawanie nowych UDF do Pig, pisząc klasę Java i informując Pig o pliku JAR.



Sama świnia ma kilka UDF. Przed wersją 0.8 był to bardzo ograniczony zestaw zawierający tylko standardowe funkcje agregujące SQL i kilka innych. W wersji 0.8 dodano dużą liczbę standardowych funkcji przetwarzania ciągów, matematyki i UDF typu złożonego.

Co to jest skarbonka?

Piggybank to zbiór UDF wniesionych przez użytkowników, który jest udostępniany wraz z usługą Pig. UDF Piggybank nie są zawarte w Pig JAR, więc musisz zarejestrować je ręcznie w swoim skrypcie. Możesz także napisać własne UDF lub użyć tych napisanych przez innych użytkowników.

Funkcje ewaluacyjne

Klasa UDF stanowi rozszerzenie klasy EvalFunc, która jest bazą dla wszystkich funkcji Eval. Wszystkie funkcje oceny rozszerzają klasę Javy „org.apache.pig.EvalFunc. „Jest sparametryzowany za pomocą zwracanego typu UDF, którym w tym przypadku jest Java String. Podstawową metodą w tej klasie jest „exec”. Pierwsza linia kodu wskazuje, że funkcja jest częścią pakietu myudfs.



Pobiera jeden rekord i zwraca jeden wynik, który będzie wywoływany dla każdego rekordu przechodzącego przez potok wykonywania. Zajmuje krotkę, która zawiera wszystkie pola, które skrypt przekazuje do UDF jako dane wejściowe. Następnie zwraca typ, według którego sparametryzowano EvalFunc.

Ta funkcja jest wywoływana w każdej krotce danych wejściowych. Dane wejściowe do funkcji to krotka z parametrami wejściowymi w kolejności, w jakiej są przekazywane do funkcji w skrypcie Pig. W poniższym przykładzie funkcja przyjmuje ciąg znaków jako dane wejściowe. Poniższa funkcja konwertuje ciąg z małych liter na wielkie. Po zaimplementowaniu funkcji należy ją skompilować i dołączyć do pliku JAR.

losowa klasa w przykładzie java
pakiet myudfs import java.io.IOException import org.apache.pig.EvalFunc import org.apache.pig.data.Tuple klasa publiczna UPPER rozszerza EvalFunc {public String exec (wejście Tuple) rzuca IOException {if (input == null || input.size () == 0) return null try {String str = (String) input.get (0) return str.toUpperCase ()} catch (Exception e) {throw new IOException ('Przechwycony wiersz wejściowy przetwarzania wyjątku', e)}}}

Funkcje agregujące:

Funkcje agregujące to kolejny popularny typ funkcji Eval. Funkcje agregujące są zwykle stosowane do zgrupowanych danych. Funkcja Aggregate pobiera pakiet i zwraca wartość skalarną. Ciekawą i cenną cechą wielu funkcji Aggregate jest to, że można je obliczać przyrostowo w sposób rozproszony. W świecie Hadoop oznacza to, że obliczenia częściowe mogą być wykonane przez Map i Combiner, a wynik końcowy może być obliczony przez Reducera.

Bardzo ważne jest, aby upewnić się, że funkcje agregujące, które są algebraiczne, są zaimplementowane jako takie. Przykładami tego typu są wbudowane liczniki, MIN, MAKS i ŚREDNIA.

LICZYĆ jest przykładem funkcji algebraicznej, w której możemy policzyć liczbę elementów w podzbiorze danych, a następnie zsumować liczby, aby uzyskać ostateczny wynik. Przyjrzyjmy się implementacji funkcji COUNT:

public class COUNT extends EvalFunc implementuje Algebraic {public Long exec (wejście krotki) rzuca IOException {return count (input)} public String getInitial () {return Initial.class.getName ()} public String getIntermed () {return Intermed.class. getName ()} public String getFinal () {return Final.class.getName ()} statyczna klasa publiczna Initial extends EvalFunc {public Tuple exec (Tuple input) throws IOException {return TupleFactory.getInstance (). newTuple (count (input)) }} static public class Intermed extends EvalFunc {public Tuple exec (Tuple input) throws IOException {return TupleFactory.getInstance (). newTuple (sum (input))}} static public class Final extends EvalFunc {public Tuple exec (wejście krotki) rzuca IOException {return sum (input)}} static protected Long count (Tuple input) throws ExecException {Object values ​​= input.get (0) if (values ​​instanceof DataBag) return ((DataBag) values) .size () else if (values) instanceof Map) zwraca nowe Long (((Map) values) .size ())} static protected Long sum (Tuple i nput) rzuca ExecException, NumberFormatException {DataBag values ​​= (DataBag) input.get (0) long sum = 0 for (Iterator (Tuple) it = values.iterator () it.hasNext ()) {Tuple t = it.next ( ) sum + = (Long) t.get (0)} return sum}}

COUNT implementuje interfejs algebraiczny, który wygląda następująco:

publiczny interfejs Algebraic {public String getInitial () public String getIntermed () public String getFinal ()}

Aby funkcja była algebraiczna, musi zaimplementować interfejs algebraiczny składający się z definicji trzech klas pochodzących z EvalFunc. Kontrakt polega na tym, że funkcja execfunction klasy Initial jest wywoływana raz i przekazywana do oryginalnej krotki wejściowej. Jego wynikiem jest krotka zawierająca częściowe wyniki. Funkcję exec klasy Intermed można wywołać zero lub więcej razy i przyjmuje jako dane wejściowe krotkę zawierającą częściowe wyniki utworzone przez klasę Initial lub przez wcześniejsze wywołania klasy Intermed i tworzy krotkę z innym częściowym wynikiem. Na koniec wywoływana jest funkcja exec klasy Final, która daje ostateczny wynik jako typ skalarny.

Funkcje filtra:

Funkcje filtrujące to funkcje Eval, które zwracają wartość logiczną. Można go używać wszędzie tam, gdzie odpowiednie jest wyrażenie logiczne, w tym operator FILTER lub wyrażenie Bincond. Apache Pig nie obsługuje w pełni wartości logicznych, więc funkcje filtru nie mogą pojawiać się w instrukcjach, takich jak „Foreach”, gdzie wyniki są wysyłane do innego operatora. Jednak funkcji filtru można używać w instrukcjach filtru.

Poniższy przykład implementuje funkcję IsEmpty:

import java.io.IOException import java.util.Map import org.apache.pig.FilterFunc import org.apache.pig.PigException import org.apache.pig.backend.executionengine.ExecException import org.apache.pig.data.DataBag import org.apache.pig.data.Tuple import org.apache.pig.data.DataType / ** * Określa, czy torba lub mapa jest pusta. * / public class IsEmpty extends FilterFunc {@Override public Boolean exec (wejście Tuple) rzuca IOException {try {Object values ​​= input.get (0) if (values ​​instanceof DataBag) return ((DataBag) values) .size () == 0 else if (wartości instanceof Map) return ((Map) values) .size () == 0 else {int errCode = 2102 String msg = 'Nie można przetestować' + DataType.findTypeName (values) + 'dla pustki.' throw new ExecException (msg, errCode, PigException.BUG)}} catch (ExecException ee) {throw ee}}}