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?
È 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.
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
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.
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. –
+1 sul commento precedente. Ma penso che dal momento che è nuovo di SO, potrebbe non aver capito come funzionano le cose qui. –