Jaka jest różnica między partycjonowaniem i grupowaniem tabeli w gałęzi Hive?

133

Wiem, że obie są wykonywane na kolumnie w tabeli, ale jak każda operacja jest inna.

NishM
źródło

Odpowiedzi:

254

Partycjonowanie danych jest często używane do poziomego rozkładania obciążenia, co ma korzystny wpływ na wydajność i pomaga w logicznej organizacji danych. Przykład : jeśli mamy do czynienia z dużą employeetabelą i często uruchamiamy zapytania z WHEREklauzulami, które ograniczają wyniki do konkretnego kraju lub działu. Aby uzyskać szybszą odpowiedź na zapytanie, tabela Hive może być PARTITIONED BY (country STRING, DEPT STRING). Tabele partycjonowania zmieniają strukturę magazynu danych, a Hive utworzy teraz podkatalogi odzwierciedlające strukturę partycjonowania, taką jak

... / workers / country = ABC / DEPT = XYZ .

Jeśli limit zapytań dla pracownika z country=ABC, będzie skanował zawartość tylko jednego katalogu country=ABC. Może to znacznie poprawić wydajność zapytań, ale tylko wtedy, gdy schemat partycjonowania odzwierciedla typowe filtrowanie. Funkcja partycjonowania jest bardzo przydatna w Hive, jednak projekt, który tworzy zbyt wiele partycji, może zoptymalizować niektóre zapytania, ale może być szkodliwy dla innych ważnych zapytań. Inną wadą jest posiadanie zbyt wielu partycji, to duża liczba plików i katalogów Hadoop, które są tworzone niepotrzebnie i stanowią obciążenie dla NameNode, ponieważ musi on przechowywać wszystkie metadane systemu plików w pamięci.

Bucketing to kolejna technika rozkładania zestawów danych na łatwiejsze do zarządzania części. Na przykład załóżmy, że tabela używająca datepartycji najwyższego poziomu i partycji employee_iddrugiego poziomu prowadzi do zbyt wielu małych partycji. Zamiast tego, jeśli podzielimy tabelę pracowników i użyjemy jej employee_idjako kolumny do grupowania, wartość tej kolumny zostanie zaszyfrowana przez liczbę zdefiniowaną przez użytkownika do segmentów. Rekordy z tym samym employee_id będą zawsze przechowywane w tym samym zasobniku. Zakładając, że liczba employee_idjest znacznie większa niż liczba koszy, każdy z nich będzie miał wiele employee_id. Tworząc tabelę możesz określić jakCLUSTERED BY (employee_id) INTO XX BUCKETS;gdzie XX to liczba segmentów. Bucketing ma kilka zalet. Liczba segmentów jest stała, więc nie zmienia się wraz z danymi. Jeśli dwie tabele są podzielone według employee_id, Hive może utworzyć logicznie poprawne próbkowanie. Bucketing pomaga również w wydajnym łączeniu po stronie mapy itp.

Navneet Kumar
źródło
4
Dzięki Navneet. Czy możesz jednak wyjaśnić, jak zachodzi dzielenie na partycje podczas partycjonowania? Załóżmy, że jeśli określimy 32 zasobniki w klauzuli CLUSED BY, a instrukcja CREATE TABLE zawiera również klauzulę Partitioning, w jaki sposób partycje i zasobniki będą wspólnie zarządzane? Czy liczba partycji będzie ograniczona do 32? CZY dla każdej partycji zostaną utworzone 32 zasobniki? Czy każdy zasobnik jest plikiem HDFS?
sgsi
12
Tabela gałęzi może mieć zarówno podział na partycje, jak i segmentowanie. Na podstawie klauzuli partycji dla każdej partycji zostaną utworzone 32 zasobniki. Tak plik HDFS.
Navneet Kumar
7
@sgsi Partycja to folder, a wiadro to plik.
leftjoin
12
Dla przypomnienia, ta odpowiedź pochodzi z tekstu z książki Programming Hive (O'Reilly, 2012).
ianmcook
1
Ten link okazał się przydatny. Zawiera informacje, które zwiększą wartość tej odpowiedzi. linkedin.com/pulse/…
Alex Raj Kaliamoorthy
133

W poprzednich wyjaśnieniach brakuje kilku szczegółów. Aby lepiej zrozumieć, jak działa partycjonowanie i grupowanie, należy przyjrzeć się, jak dane są przechowywane w gałęzi. Powiedzmy, że masz stolik

CREATE TABLE mytable ( 
         name string,
         city string,
         employee_id int ) 
PARTITIONED BY (year STRING, month STRING, day STRING) 
CLUSTERED BY (employee_id) INTO 256 BUCKETS

wtedy gałąź będzie przechowywać dane w hierarchii katalogów, takiej jak

/user/hive/warehouse/mytable/y=2015/m=12/d=02

Musisz więc zachować ostrożność podczas partycjonowania, ponieważ jeśli na przykład podzielisz na partycje według identyfikatora pracownika i masz miliony pracowników, w końcu będziesz mieć miliony katalogów w swoim systemie plików. Termin „ liczność ” odnosi się do liczby możliwych wartości, jakie może mieć pole. Na przykład, jeśli masz pole „kraj”, krajów na świecie jest około 300, więc liczność będzie wynosić ~ 300. W przypadku pola takiego jak „timestamp_ms”, które zmienia się co milisekundę, liczność może wynosić miliardy. Ogólnie rzecz biorąc, wybierając pole do partycjonowania, nie powinno ono mieć wysokiej liczności, ponieważ w systemie plików będzie o wiele za dużo katalogów.

Z drugiej strony grupowanie, czyli segmentowanie, da stałą liczbę plików, ponieważ określa się liczbę segmentów. To, co zrobi, to zajmie pole, obliczy hash i przypisze rekord do tego zasobnika. Ale co się stanie, jeśli użyjesz, powiedzmy, 256 segmentów, a pole, na którym się znajdujesz, ma niską liczność (na przykład jest to stan USA, więc może być tylko 50 różnych wartości)? Będziesz mieć 50 zasobników z danymi i 206 zasobników bez danych.

Ktoś już wspomniał, jak partycje mogą radykalnie zmniejszyć ilość zapytanych danych. Tak więc w mojej przykładowej tabeli, jeśli chcesz wykonywać zapytania tylko od określonej daty do przodu, partycjonowanie według roku / miesiąca / dnia radykalnie zmniejszy ilość operacji we / wy. Myślę, że ktoś wspomniał również o tym, jak bucketing może przyspieszyć łączenie z innymi tabelami, które mają dokładnie takie same przedziały , więc w moim przykładzie, jeśli łączysz dwie tabele na tym samym identyfikatorze pracownika, ul może wykonać łączenie segmentu po wiadrze (jeszcze lepiej jeśli są już posortowane według identyfikatora pracownika, ponieważ ma zamiar scalić części, które są już posortowane, co działa w czasie liniowym aka O (n)).

Tak więc segmentowanie działa dobrze, gdy pole ma wysoką kardynalność, a dane są równomiernie rozmieszczone w zasobnikach. Partycjonowanie działa najlepiej, gdy liczność pola partycjonowania nie jest zbyt wysoka.

Ponadto, można podzielić na wielu polach , z rozkazem (rok / miesiąc / dzień jest dobrym przykładem), natomiast można wiadro na tylko jedno pole .

Roberto Congiu
źródło
Czy możesz wyjaśnić zachowanie CLUSTERED-BY z SORTED-BY na przykładzie? Jak na mój przykład, SORTED-BY nic nie robi. Czy coś mi brakuje.
Jagadish Talluri
2
CLUSTERED BY x, y jest jak pisanie DISTRIBUTE BY x, y SORT BY x, y (patrz cwiki.apache.org/confluence/display/Hive/... ), więc dodanie SORT BY do CLUSTERED BY nie ma żadnego efektu.
Roberto Congiu
Co ciekawe, zgadzam się na użycie w zapytaniu wybierającym. Ale zastanawiałem się, dlaczego ludzie używają grupowania i sortowania według razem w instrukcji tworzenia tabeli. Jeśli w DDL nie ma znaczenia SORTED BY, dlaczego występuje to słowo kluczowe? Nie rozumiem.
Jagadish Talluri
SORTED BY ma być używany z DISTRIBUTED BY. Na przykład możesz chcieć dystrybuować według identyfikatora użytkownika i sortować według czasu w zasobniku. CLUSTER BY to tylko skrót do sytuacji, gdy klauzule SORTED BY i DISTRIBUTED BY są takie same. Jedyne co mogę myśleć o to, czy jesteś wypłacaniu przez X, Y i sortując X, Y i Z
Roberto Congiu
Nie jestem pewien, co masz na myśli mówiąc „możesz czerpać tylko na jednym polu”. Myślę, że możliwe jest dzielenie na wiele pól, funkcja haszująca po prostu weźmie wszystkie pola i połączy je.
Istvan
18

Myślę, że spóźniłem się z odpowiedzią na to pytanie, ale ciągle pojawia się ono w moim kanale.

Navneet udzielił doskonałej odpowiedzi. Dodając do tego wizualnie.

Partycjonowanie pomaga w eliminacji danych, jeśli jest używane w klauzuli WHERE, gdzie grupowanie pomaga w organizowaniu danych z każdej partycji w wiele plików, tak aby ten sam zestaw danych był zawsze zapisywany w tym samym zasobniku. Bardzo pomaga w łączeniu kolumn.

Załóżmy, że masz tabelę z pięcioma kolumnami: nazwa, data_serwera, jakaś_kol3, jakaś_kol4 i jakaś_kol5. Załóżmy, że podzieliłeś tabelę na serwer_data i podzieliłeś na kolumnę z nazwą w 10 segmentach , struktura plików będzie wyglądać mniej więcej tak, jak poniżej.

  1. server_date = xyz
    • 00000_0
    • 00001_0
    • 00002_0
    • ........
    • 00010_0

Tutaj server_date = xyz to partycja, a 000 plików to pojemniki na każdej partycji. Zasobniki są obliczane na podstawie niektórych funkcji skrótu, więc wiersze o nazwie = Sandy zawsze będą znajdować się w tym samym zasobniku.

Priyesh
źródło
2
Według Roberta w powyższej odpowiedzi data_serwera byłaby złym przykładem podziału na partycje, ponieważ jego wartość liczności jest naprawdę wysoka. W rezultacie będziesz miał zbyt wiele folderów w plikach hdf.
Gaurang Shah
server_date jest wymieniony tutaj jako przykład. W prawdziwym świecie podział zazwyczaj odbywa się tak, jak to przedstawił Roberto, dzieląc datę na rok / miesiąc / dzień. Tak powinno być.
Priyesh
18

Partycjonowanie ula:

Partycja dzieli duże ilości danych na wiele wycinków w oparciu o wartość kolumny (kolumn) tabeli.

Załóżmy, że przechowujesz informacje o ludziach z całego świata w ponad 196 krajach, obejmujących około 500 milionów wpisów. Jeśli chcesz zapytać osoby z określonego kraju (Watykanu), w przypadku braku podziału na partycje, musisz przeskanować wszystkie 500 milionów wpisów, aby pobrać nawet tysiące wpisów z danego kraju. Jeśli podzielisz tabelę na partycje według kraju, możesz dostroić proces zapytań, po prostu sprawdzając dane tylko dla jednej partycji krajowej. Partycja Hive tworzy oddzielny katalog dla wartości kolumn.

Plusy:

  1. Rozłóż obciążenie wykonawcze w poziomie
  2. Szybsze wykonywanie zapytań w przypadku partycji z małą ilością danych. np. Pobierz populację z „ Watykanu ” zwraca bardzo szybko, zamiast przeszukiwać całą populację świata.

Cons:

  1. Możliwość utworzenia zbyt wielu małych partycji - zbyt wielu katalogów.
  2. Skuteczne w przypadku danych o małej objętości dla danej partycji. Jednak wykonanie niektórych zapytań, takich jak grupowanie według dużej ilości danych, nadal zajmuje dużo czasu. Np. grupowanie populacji Chin zajmie dużo czasu w porównaniu do grupowania ludności w Watykanie. Partycja nie rozwiązuje problemu z odpowiedzią w przypadku przekrzywienia danych w kierunku określonej wartości partycji.

Wiaderko ula:

Bucketing rozkłada dane na łatwiejsze do zarządzania lub równe części.

Dzięki partycjonowaniu istnieje możliwość tworzenia wielu małych partycji na podstawie wartości kolumn. Jeśli zdecydujesz się na segmentowanie, ograniczasz liczbę segmentów do przechowywania danych. Liczba ta jest definiowana podczas skryptów tworzenia tabel.

Plusy

  1. Ze względu na równe ilości danych w każdej partycji, połączenia po stronie mapy będą szybsze.
  2. Szybsza odpowiedź na zapytanie, takie jak partycjonowanie

Cons

  1. Możesz zdefiniować liczbę segmentów podczas tworzenia tabeli, ale ładowanie takiej samej ilości danych musi być wykonane ręcznie przez programistów.
Ravindra babu
źródło
13

Zanim przejdziemy do tego Bucketing, musimy zrozumieć, co Partitioningto jest. Weźmy jako przykład poniższą tabelę. Zauważ, że w poniższym przykładzie podałem tylko 12 rekordów dla zrozumienia poziomu początkującego. W scenariuszach czasu rzeczywistego możesz mieć miliony rekordów.

wprowadź opis obrazu tutaj



PARTYCJONOWANIE
---------------------
Partitioning służy do uzyskania wydajności podczas wykonywania zapytań dotyczących danych. Na przykład w powyższej tabeli, jeśli napiszemy poniższy sql, należy przeskanować wszystkie rekordy w tabeli, co zmniejsza wydajność i zwiększa narzut.

select * from sales_table where product_id='P1'

Aby uniknąć pełnego skanowania tabeli i czytać tylko rekordy z nim związane product_id='P1', możemy podzielić (podzielić pliki tabeli gałęzi) na wiele plików na podstawie product_idkolumny. W ten sposób plik tabeli gałęzi zostanie podzielony na dwa pliki, jeden zi product_id='P1'drugi z product_id='P2'. Teraz, gdy wykonamy powyższe zapytanie, przeskanuje ono tylko product_id='P1'plik.

../hive/warehouse/sales_table/product_id=P1
../hive/warehouse/sales_table/product_id=P2

Składnia tworzenia partycji jest podana poniżej. Zauważ, że nie powinniśmy używać product_iddefinicji kolumny razem z niepartycjonowanymi kolumnami w poniższej składni. Powinno to być tylko w partitioned byklauzuli.

create table sales_table(sales_id int,trans_date date, amount int) 
partitioned by (product_id varchar(10))

Wady : Podczas partycjonowania powinniśmy być bardzo ostrożni. Oznacza to, że nie należy go używać w przypadku kolumn, w których liczba powtarzających się wartości jest bardzo mniejsza (szczególnie w kolumnach klucza podstawowego), ponieważ zwiększa liczbę partycjonowanych plików i zwiększa obciążenie dla Name node.



BUCKETING
------------------
Bucketing służy do przezwyciężenia tego cons, o czym wspomniałem w sekcji o partycjonowaniu. Powinno to być używane, gdy w kolumnie jest bardzo mało powtarzających się wartości (przykład - kolumna klucza podstawowego). Jest to podobne do koncepcji indeksu w kolumnie klucza podstawowego w RDBMS. W naszej tabeli możemy wziąć Sales_Idkolumnę do wiaderkowania. Przyda się, gdy będziemy musieli odpytać sales_idkolumnę.

Poniżej znajduje się składnia segmentowania.

create table sales_table(sales_id int,trans_date date, amount int) 
partitioned by (product_id varchar(10)) Clustered by(Sales_Id) into 3 buckets

Tutaj dalej podzielimy dane na kilka dodatkowych plików na partycjach.

wprowadź opis obrazu tutaj

Ponieważ określiliśmy 3zasobniki, jest on podzielony na 3 pliki dla każdego product_id. Używa go wewnętrznie modulo operatordo określenia, w którym wiadrze każdy sales_idpowinien być przechowywany. Na przykład, dla product_id='P1', sales_id=1będzie przechowywany w pliku 000001_0 (tj. 1% 3 = 1), sales_id=2będzie przechowywany w pliku 000002_0 (tj. 2% 3 = 2), sales_id=3będzie przechowywany w pliku 000000_0 (tj. 3% 3 = 0) itd.

Sarath Avanavu
źródło
W przypadku liczbowych kolumn grupowanych, czy zawsze wystarczy mod na podstawie liczby segmentów? Czy w przypadku kolumn klastrowych o wartościach łańcuchowych używa języka Java hashCode()z ciągu jako funkcji skrótu? Czy programista może wybrać funkcję skrótu?
Don Smith
Najwyraźniej (i na podstawie moich eksperymentów) gałąź używa odmiany metody hashCode () Javy : github.com/apache/hive/blob/release-1.1.0/serde/src/java/org/… . Wspomniano o tym tutaj: stackoverflow.com/questions/30594038/… .
Don Smith
4

Różnica polega na tym, że dzielenie grupuje pliki według nazwy kolumny, a partycjonowanie dzieli pliki według określonej wartości w tabeli

Mam nadzieję, że poprawnie to zdefiniowałem

uriya harel
źródło
1

Tutaj są świetne odpowiedzi. Chciałbym, żeby było to krótkie, aby zapamiętać różnicę między partycjami a zasobnikami.

Zwykle partycjonujesz na mniej unikalnej kolumnie. I łyżką na najbardziej unikalnej kolumnie.

Przykład, jeśli weźmiesz pod uwagę populację świata z krajem, imieniem i nazwiskiem osoby i jej identyfikatorem biometrycznym jako przykładem. Jak możesz się domyślić, pole kraju byłoby mniej unikalną kolumną, a identyfikator biometryczny byłby najbardziej unikalną kolumną. Idealnie byłoby więc podzielić tabelę według kraju i podzielić ją według identyfikatora biometrycznego.

SVK
źródło
-1

Używanie partycji w tabeli Hive jest wysoce zalecane z poniższego powodu -

  • Wstawianie do tabeli Hive powinno być szybsze (ponieważ używa wielu wątków do zapisywania danych na partycjach)
  • Zapytanie z tabeli Hive powinno być wydajne z małym opóźnieniem.

Przykład: -

Załóżmy, że plik wejściowy (100 GB) jest ładowany do tabeli temp-hive-table i zawiera dane bankowe z różnych regionów geograficznych.

Tabela ula bez partycji

Insert into Hive table Select * from temp-hive-table

/hive-table-path/part-00000-1  (part size ~ hdfs block size)
/hive-table-path/part-00000-2
....
/hive-table-path/part-00000-n

Problem z tym podejściem polega na tym, że skanuje całe dane w poszukiwaniu dowolnego zapytania uruchomionego w tej tabeli. Czas odpowiedzi będzie długi w porównaniu z innymi podejściami, w których używane są partycjonowanie i Bucketing.

Stół ula z przegrodą

Insert into Hive table partition(country) Select * from temp-hive-table

/hive-table-path/country=US/part-00000-1       (file size ~ 10 GB)
/hive-table-path/country=Canada/part-00000-2   (file size ~ 20 GB)
....
/hive-table-path/country=UK/part-00000-n       (file size ~ 5 GB)

Zalety - tutaj można uzyskać szybszy dostęp do danych, jeśli chodzi o przeszukiwanie danych dla określonych transakcji geograficznych. Wady - Wstawianie / wysyłanie zapytań do danych można dodatkowo ulepszyć, dzieląc dane w każdej partycji. Zobacz opcję Bucketing poniżej.

Tabela ula z partycjami i zasobnikami

Uwaga: Utwórz tabelę gałęzi… z „CLUSTERED BY (Partiton_Column) w 5 zasobnikach

Insert into Hive table partition(country) Select * from temp-hive-table

/hive-table-path/country=US/part-00000-1       (file size ~ 2 GB)
/hive-table-path/country=US/part-00000-2       (file size ~ 2 GB)
/hive-table-path/country=US/part-00000-3       (file size ~ 2 GB)
/hive-table-path/country=US/part-00000-4       (file size ~ 2 GB)
/hive-table-path/country=US/part-00000-5       (file size ~ 2 GB)

/hive-table-path/country=Canada/part-00000-1   (file size ~ 4 GB)
/hive-table-path/country=Canada/part-00000-2   (file size ~ 4 GB)
/hive-table-path/country=Canada/part-00000-3   (file size ~ 4 GB)
/hive-table-path/country=Canada/part-00000-4   (file size ~ 4 GB)
/hive-table-path/country=Canada/part-00000-5   (file size ~ 4 GB)

....
/hive-table-path/country=UK/part-00000-1       (file size ~ 1 GB)
/hive-table-path/country=UK/part-00000-2       (file size ~ 1 GB)
/hive-table-path/country=UK/part-00000-3       (file size ~ 1 GB)
/hive-table-path/country=UK/part-00000-4       (file size ~ 1 GB)
/hive-table-path/country=UK/part-00000-5       (file size ~ 1 GB)

Zalety - szybsze wstawianie. Szybsze zapytanie.

Wady - Bucketing spowoduje utworzenie większej liczby plików. W niektórych przypadkach może wystąpić problem z wieloma małymi plikami

Mam nadzieję, że to pomoże !!

Ajay Ahuja
źródło