2016-08-02 5 views
6

Ich habe eine sehr große Tabelle in Hive, von dem wir eine Teilmenge von Partitionen laden müssen. Es sieht etwa so aus:Dynamisch laden Partitionen in Hive mit Prädikat Pushdown

CREATE EXTERNAL TABLE table1 (
    col1 STRING 
) PARTITIONED BY (p_key STRING); 

ich bestimmte Partitionen wie folgt laden:

SELECT * FROM table1 WHERE p_key = 'x'; 

mit p_key ist der Schlüssel, auf dem table1 partitioniert ist. Wenn ich es direkt in der WHERE-Klausel fest codiere, ist alles gut. Ich habe jedoch eine andere Abfrage, die berechnet, welche Partitionen ich brauche. Es ist komplizierter als das, aber wir wollen es einfach definieren als:

SELECT DISTINCT p_key FROM table2; 

So, jetzt sollte ich in der Lage sein, eine schmutzige Abfrage wie folgt zu konstruieren:

SELECT * FROM table1 
WHERE p_key IN (SELECT DISTINCT p_key FROM table2); 

Oder geschrieben als innere Verknüpfung:

SELECT t1.* FROM table1 t1 
JOIN (SELECT DISTINCT p_key FROM table2) t2 ON t1.p_key = t2.p_key 

Wenn ich dies jedoch ausführe, dauert es genug Zeit, um mich glauben zu lassen, dass es einen vollständigen Tabellenscan macht. In der Erklärung für die obigen Abfragen kann ich auch sehen, dass das Ergebnis der DISTINCT-Operation im Reduzierer und nicht im Mapper verwendet wird, was bedeutet, dass der Mapper nicht wissen könnte, welche Partitionen geladen werden sollen oder nicht. Zugegeben, ich bin nicht ganz mit der Erklärung von Hive vertraut, daher kann ich etwas übersehen.

Ich habe diese Seite gefunden: MapJoin and Partition Pruning auf dem Hive Wiki und die entsprechende ticket zeigt an, dass es in Version 0.11.0 veröffentlicht wurde. Also ich sollte haben es.

Ist es möglich, dies zu tun? Wenn das so ist, wie?

+0

Es hängt stark von Ihrem Datenformat ab. Haben Sie einen Index für die Spalte erstellt? –

+0

@ThomasJungblut Ich habe keinen Index für die Spalte, nein, aber es ist eine Partition Spalte. – KennethJ

Antwort

0

Ich bin nicht sicher, wie mit MapJoin zu helfen, aber im schlimmsten Fall könnten Sie dynamisch zweite Abfrage mit so etwas wie erstellen:

SELECT concat('SELECT * FROM table1 WHERE p_key IN (', 
       concat_ws(',',collect_set(p_key)), 
       ')') 
    FROM table2; 

dann erhaltene Ergebnis execute. Der Abfrageprozessor sollte in der Lage sein, nicht benötigte Partitionen zu entfernen.

Verwandte Themen