2012-07-08 21 views
9

Ho una query Hive che seleziona circa 30 colonne e circa 400.000 record e li inserisce in un'altra tabella. Ho un join nella mia clausola SQL, che è solo un join interno.Ottimizzazione delle prestazioni di una query Hive

La query non riesce a causa di un limite di sovraccarico del GC Java superato.

Ciò che è strano è che se rimuovo la clausola join e seleziono semplicemente i dati dalla tabella (volume leggermente superiore), la query funziona correttamente.

Sono abbastanza nuovo per Hive. Non riesco a capire perché questo join stia causando eccezioni di memoria.

C'è qualcosa di cui dovrei essere a conoscenza riguardo a come scrivo le query Hive in modo che non causino questi problemi? Qualcuno potrebbe spiegare perché il join potrebbe causare questo problema, ma selezionando un volume maggiore di dati e lo stesso numero di colonne no.

Apprezzo i tuoi pensieri su questo. Grazie

risposta

6

Mille grazie per la risposta Mark. Molto apprezzato.

Dopo molte ore ho scoperto che l'ordine delle tabelle nell'istruzione join fa la differenza. Per prestazioni ottimali e gestione della memoria, l'ultimo join dovrebbe essere la tabella più grande.

La modifica dell'ordine dei miei tavoli nella dichiarazione di join ha risolto il problema.

vedere la più grande Tabella scorso in http://hive.apache.org/docs/r0.9.0/language_manual/joins.html

tua spiegazione di cui sopra è molto utile pure. Molte grazie

+5

Ehi, dovresti "accettare" la risposta di Mark Grover se sei d'accordo con la sua soluzione invece di accettare la tua soluzione che non è davvero una soluzione ma un apprezzamento della risposta corretta. –

+0

+1 sul commento precedente. Ma penso che dal momento che è nuovo di SO, potrebbe non aver capito come funzionano le cose qui. –

34

A seconda della versione di Hive e della configurazione, la risposta alla domanda può variare. Sarebbe più facile se fosse possibile condividere la query esatta con le istruzioni create delle due tabelle e una stima delle loro dimensioni.

Per comprendere meglio il problema, vediamo come funziona un join interno "regolare" in Hive.

Hive unirsi MapReduce:

Ecco una descrizione semplificata di come un inner join in Hive viene compilato a MapReduce. In generale, se si dispone di due tabelle t1 e t2 con una query join come:

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

Dove, T1 ha il seguente contenuto:

k_1 v1_1 
k_2 v1_2 
k_3 v1_3  

Dove, T2 ha il seguente contenuto:

k_2 v2_2 
k_3 v2_3 
k_4 v2_4  

Ci si aspetterebbe il join risultato sia

k_2 v1_2 v2_2 
k_3 v1_3 v2_3 

Supponendo che le tabelle siano memorizzate su HDFS, i loro contenuti saranno suddivisi in File Splits. Un mapper prende un file diviso come input ed emette la chiave come la colonna chiave della tabella e il valore come il composto della colonna del valore della tabella e un flag (che rappresenta da quale tabella il record proviene da ie t1 o t2) .

per T1:

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

Per t2:

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

Ora, questi record emessi fuori passare attraverso la fase di riordino dove tutti i record con gli stessi tasti sono raggruppati insieme e inviati a un riduttore. Il contesto di ciascuna operazione di riduzione è una chiave e una lista contenente tutti i valori corrispondenti a quella chiave. In pratica, un riduttore eseguirà diverse operazioni di riduzione.

Nell'esempio precedente, otterremmo i seguenti raggruppamenti:

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

Ecco cosa accade nel riduttore. Per ciascuno dei valori nell'elenco dei valori, il riduttore eseguirà una moltiplicazione se i valori corrispondono a tabelle diverse.

Per k_1, non esiste alcun valore da t2 e non viene emesso nulla.

Per k_2, una moltiplicazione di valori viene emesso - k_2, v1_2, v2_2 (poiché non v'è un valore da ciascuna tabella, 1x1 = 1)

Per k_3, una moltiplicazione di valori viene emesso - k_3, v1_3 , v2_3 (poiché vi è un valore per ogni tabella, 1x1 = 1)

Per k_4, non c'è alcun valore da t1 e non viene emesso nulla. Quindi ottieni il risultato che ti aspettavi dal tuo join interno.

Ok, quindi cosa devo fare?

  1. È possibile che i dati siano distorti. In altre parole, quando il riduttore ottiene i dati, l'elenco di valori corrispondente a qualche tasto è molto lungo e causa un errore. Per alleviare il problema, si può provare a rimbalzare la memoria disponibile per la propria JVM. Puoi farlo impostando mapred.child.java.opts su un valore come -Xmx512M nel tuo hive-site.xml. Puoi interrogare il valore attuale di questo parametro eseguendo set mapred.child.java.opts; nella tua shell Hive.

  2. Puoi provare a utilizzare le alternative al join "regolare", ad es. aderire alla mappa. La suddetta spiegazione dei join si applica ai join regolari in cui l'unione avviene nei riduttori. A seconda della versione di Hive che stai usando, Hive può essere in grado di convertire automaticamente un join regolare in map join che è più veloce (perché il join avviene in fase mappa). Per abilitare l'ottimizzazione, impostare hive.auto.convert.join su true. Questa struttura è stata introdotta nel Hive 0.7

  3. Oltre a impostare hive.auto.convert.join a true, si può anche impostare hive.optimize.skewjoin a true. Ciò funzionerà attorno al disallineamento nel problema dei dati descritto in 1.

Problemi correlati