2012-07-08 20 views
9

Mam kwerendę Hive, który wybiera około 30 kolumn i około 400 000 rekordów i wstawia je do innej tabeli. Mam jedno sprzężenie w mojej klauzuli SQL, która jest po prostu wewnętrznym złączeniem.Dostrajanie wydajności kwerendy Hive

Zapytanie kończy się niepowodzeniem z powodu przekroczenia limitu narzutowego Java GC.

Co jest dziwne, jeśli usunę klauzulę złączenia i po prostu wybiorę dane z tabeli (nieco większa objętość), to zapytanie działa poprawnie.

Jestem całkiem nowy dla Hive. Nie mogę zrozumieć, dlaczego to dołączenie powoduje wyjątki pamięci.

Czy jest coś, o czym powinienem wiedzieć w związku z pisaniem zapytań Hive, aby nie powodowały tych problemów? Czy ktoś może wyjaśnić, dlaczego sprzężenie może powodować ten problem, ale wybierając większą ilość danych i taką samą liczbę kolumn nie.

Doceniam twoje przemyślenia na ten temat. Dzięki

Odpowiedz

6

Wielkie dzięki za odpowiedź Marka. Bardzo doceniane.

Po wielu godzinach w końcu okazało się, że kolejność tabel w sprzężeniu oświadczenie robi różnicę. Aby uzyskać optymalną wydajność i zarządzanie pamięcią, ostatnie sprzężenie powinno być największą tabelą.

Zmiana kolejności moich tabel w rachunku dołączyć Naprawiono problem.

Patrz tabela Ostatnie Największy na http://hive.apache.org/docs/r0.9.0/language_manual/joins.html

Twój wyjaśnienie powyżej jest bardzo przydatna również. Wielkie dzięki

+5

Hej, powinieneś "zaakceptować" odpowiedź Marka Grover'a, jeśli zgadzasz się z jego rozwiązaniem, zamiast akceptować własne rozwiązanie, które nie jest tak naprawdę rozwiązaniem, ale zrozumieniem poprawnej odpowiedzi. –

+0

+1 w powyższym komentarzu. Ale myślę, że odkąd jest nowicjuszem w SO, mógł nie zdawać sobie sprawy, jak to działa. –

34

W zależności od wersji Hive i konfiguracji, odpowiedź na pytanie może być różna. Byłoby łatwiej, gdybyś mógł udostępnić swoje dokładne zapytanie wraz z instrukcjami tworzenia dwóch tabel i oszacowaniem ich rozmiarów.

Aby lepiej zrozumieć problem, przejrzyjmy, jak działa "normalne" sprzężenie wewnętrzne w Hive.

Hive przyłączyć MapReduce:

Oto uproszczony opis sposobu sprzężenie wewnętrzne w Ulu zostanie skompilowany do MapReduce. W ogóle, jeśli masz dwie tabele t1 i t2 z kwerendy dołączyć jak:

SELECT 
    t1.key, t1.value, t2.value 
FROM 
    t1 
    JOIN 
    t2 (ON t1.key = t2.key); 

Gdzie T1 ma następującą zawartość:

k_1 v1_1 
k_2 v1_2 
k_3 v1_3  

Gdzie, t2 ma następującą zawartość:

k_2 v2_2 
k_3 v2_3 
k_4 v2_4  

oczekujemy, że wynik przyłączyć się

k_2 v1_2 v2_2 
k_3 v1_3 v2_3 

Zakładając, że tabele są przechowywane na HDFS, ich zawartość zostanie podzielona na Podziały plików. Program odwzorowujący podejmie plik podzielony jako dane wejściowe i wyemituje klucz jako kolumnę kluczową tabeli oraz wartość jako złożony z kolumny wartości tabeli i flagi (reprezentującej tabelę, z której pochodzi rekord tj. T1 lub t2) .

Dla T1:

k_1, <v1_1, t1> 
k_2, <v1_2, t1> 
k_3, <v1_3, t1> 

Dla T2:

k_2, <v2_2, t2> 
k_3, <v2_3, t2> 
k_4, <v2_4, t2> 

Teraz te emitowane z zapisów przejść przez fazę losowego gdzie wszystkie rekordy z tych samych kluczy są zgrupowane razem i wysłane do reduktor. Kontekst każdej operacji zmniejszania to jeden klucz i lista zawierająca wszystkie wartości odpowiadające temu kluczowi. W praktyce jeden reduktor wykonuje kilka operacji redukcji.

W powyższym przykładzie, chcemy uzyskać następujące ugrupowania:

k_1, <<v1_1, t1>> 
k_2, <<v1_2, t1>, <v2_2, t2>> 
k_3, <<v1_3, t1>, <v2_3, t2>> 
k_4, <<v2_4, t2>> 

Oto, co dzieje się w reduktorze. Dla każdej wartości na liście wartości reduktor wykona mnożenie, jeśli wartości odpowiadają różnym tabelom.

Dla k_1, nie ma wartości od t2 i nic nie jest emitowany.

Na k_2, mnożenie wartości emitowane - k_2, v1_2, v2_2 (ponieważ nie ma wartość z każdej tabeli 1x1 = 1)

Na k_3, mnożenie wartości emitowane - k_3, v1_3 , v2_3 (ponieważ nie ma wartość z każdej tabeli 1x1 = 1)

Na k_4 nie ma wartość od t1 i nic nie jest emitowany. Dzięki temu uzyskasz wynik, którego oczekiwałeś od swojego wewnętrznego połączenia.

Ok, więc co mam zrobić?

  1. Możliwe, że dane są pochylone. Innymi słowy, gdy reduktor pobiera dane, lista wartości odpowiadająca pewnemu kluczowi jest bardzo długa, co powoduje błąd. Aby złagodzić problem, możesz spróbować zwiększyć pamięć dostępną dla maszyny JVM. Można to zrobić, ustawiając wartość mapred.child.java.opts na wartość podobną do -Xmx512M w pliku Hive-Site.xml. Możesz sprawdzić aktualną wartość tego parametru wykonując set mapred.child.java.opts; w swojej powłoce Hive.

  2. Można spróbować użyć alternatywy dla „regular” przyłączyć, na przykład dołączenie do mapy. Powyższe wyjaśnienie łączenia ma zastosowanie do regularnych połączeń, w których łączenie odbywa się w reduktorach. W zależności od wersji Hive, Hive może automatycznie przekonwertować zwykłe dołączenie do łączenia mapy, które jest szybsze (ponieważ dołączenie odbywa się w fazie mapy). Aby włączyć optymalizację, ustaw hive.auto.convert.join na true. Ten obiekt został wprowadzony w Hive 0.7

  3. Oprócz ustawiania hive.auto.convert.join do true, można także ustawić hive.optimize.skewjoin do true. Spowoduje to zmianę ukośności w problemie z danymi opisanym w 1.