2012-06-29 8 views
18

Ich habe eine Tabelle als solche definiert:Beim Erstellen einer externen Tabelle in Hive kann ich den Speicherort auf bestimmte Dateien in einem Verzeichnis zeigen?

create external table PageViews (Userid string, Page_View string) 
partitioned by (ds string) 
row format as delimited fields terminated by ',' 
stored as textfile location '/user/data'; 

Ich möchte nicht alle Dateien im Verzeichnis/user/Datenverzeichnis als Teil der Tabelle verwendet werden. Ist es mir möglich folgendes zu tun?

location 'user/data/*.csv' 

Antwort

8

Ich stieß auf diesen Thread, als ich ein ähnliches Problem zu lösen hatte. Ich konnte es mit einem benutzerdefinierten SerDe beheben. Ich fügte dann SerDe-Eigenschaften hinzu, die anzeigten, welche RegEx auf die Dateinamenmuster für eine bestimmte Tabelle anzuwenden war.

Ein benutzerdefinierter SerDe könnte zu übertrieben erscheinen, wenn Sie nur mit Standard-CSV-Dateien arbeiten, hatte ich ein komplexeres Dateiformat zu bewältigen. Dennoch ist dies eine sehr praktikable Lösung, wenn Sie nicht davor zurückschrecken Java zu schreiben. Dies ist besonders nützlich, wenn Sie die Daten an Ihrem Speicherort nicht umstrukturieren können und Sie nach einem sehr spezifischen Dateimuster in einem unverhältnismäßig großen Dateisatz suchen.

> CREATE EXTERNAL TABLE PageViews (Userid string, Page_View string) 
> ROW FORMAT SERDE 'com.something.MySimpleSerDe' 
> WITH SERDEPROPERTIES ("input.regex" = "*.csv") 
> LOCATION '/user/data'; 
+0

funktioniert nicht mit opencsvserde – thebluephantom

6

Nein, das geht derzeit nicht. Es ist ein JIRA-Ticket geöffnet, das die Regex-Auswahl von enthaltenen Dateien für Hive-Tabellen zulässt (https://issues.apache.org/jira/browse/HIVE-951).

Für jetzt ist Ihre beste Wette, eine Tabelle über ein anderes Verzeichnis zu erstellen und kopieren Sie einfach die Dateien, die Sie abfragen möchten.

+1

Ich sehe dieses Problem ist noch offen ... – Haimei

15

Was kmosley gesagt ist wahr. Ab jetzt können Sie bestimmte Dateien nicht selektiv als Teil Ihrer Hive-Tabelle auswählen. Es gibt jedoch 2 Möglichkeiten, um es zu umgehen.

Option 1: Sie können alle CSV-Dateien in ein anderes HDFS-Verzeichnis verschieben und darüber hinaus eine Hive-Tabelle erstellen. Wenn es für Sie besser funktioniert, können Sie ein Unterverzeichnis (z. B. csv) in Ihrem vorhandenen Verzeichnis erstellen, das alle CSV-Dateien enthält. Sie können dann eine Hive-Tabelle oberhalb dieses Unterverzeichnisses erstellen. Beachten Sie, dass alle oberhalb des übergeordneten Verzeichnisses erstellten Hive-Tabellen KEINE Daten aus dem Unterverzeichnis enthalten.

Option 2: Sie können Ihre Fragen ändern INPUT__FILE__NAME genannt Verwendung einer virtuellen Spalte zu machen.

Ihre Anfrage würde in etwa so aussehen:

SELECT 
    * 
FROM 
    my_table 
WHERE 
    INPUT__FILE__NAME LIKE '%csv'; 

Die schlecht Wirkung dieses Ansatzes besteht darin, dass die Hive-Abfrage über gesamten Daten in dem Verzeichnis Churn haben, auch wenn Sie nur über bestimmte Dateien gepflegt. Die Abfrage filtert keine Dateien basierend auf dem Prädikat mit INPUT__FILE__NAME heraus. Es wird nur herausgefiltert, dass die Datensätze, die nicht aus dem Prädikat kommen, während der Map-Phase INPUT__FILE__NAME verwenden (folglich werden alle Datensätze aus bestimmten Dateien herausgefiltert), aber die Mapper würden auch auf unnötigen Dateien laufen. Es wird Ihnen das richtige Ergebnis geben, könnte einige, wahrscheinlich geringe, Leistungs Overhead haben. Der Vorteil dieses Ansatzes besteht darin, dass Sie die gleiche Hive-Tabelle verwenden können, wenn Sie mehrere Dateien in Ihrer Tabelle haben und die Möglichkeit haben möchten, alle Dateien aus dieser Tabelle (oder ihrer Partition) in einigen Abfragen und einer Teilmenge abzufragen der Dateien in anderen Abfragen. Sie könnten die virtuelle Spalte INPUT__FILE__NAME verwenden, um dies zu erreichen.Als Beispiel: , wenn eine Partition in Ihrem HDFS Verzeichnis /user/hive/warehouse/web_logs/ sah aus wie:

/user/hive/warehouse/web_logs/dt=2012-06-30/ 
    /user/hive/warehouse/web_logs/dt=2012-06-30/00.log 
    /user/hive/warehouse/web_logs/dt=2012-06-30/01.log 
    . 
    . 
    . 
    /user/hive/warehouse/web_logs/dt=2012-06-30/23.log 

Ihre Tabellendefinition sagen Lassen Sie sah aus wie:

CREATE EXTERNAL TABLE IF NOT EXISTS web_logs_table (col1 STRING) 
PARTITIONED BY (dt STRING) 
LOCATION '/user/hive/warehouse/web_logs'; 

Nachdem die entsprechenden Partitionen hinzufügen, Sie alle Protokolle abfragen könnten in die Partition eine Abfrage wie mit:

SELECT 
    * 
FROM 
    web_logs_table w 
WHERE 
    dt='2012-06-30'; 

wenn Sie jedoch nur über die Protokolle von der ersten Stunde des Tages betreut, konnte man abfragen, um die Protokolle für die erste Stunde mit einer Abfrage wie:

SELECT 
    * 
FROM 
    web_logs_table w 
WHERE 
    dt ='2012-06-30' 
    AND INPUT__FILE__NAME='00.log'; 

Ein weiterer ähnlicher Anwendungsfall könnte ein Verzeichnis sein, das Web-Logs aus verschiedenen Bereichen und verschiedene Abfragen enthält müssen Protokolle auf verschiedene Gruppen von Domänen analysieren. Die Abfragen können Domänen mit der virtuellen Spalte INPUT__FILE__NAME herausfiltern.

In den beiden obigen Anwendungsfällen würde das Problem mit einer Unterpartition für Stunde oder Domäne gelöst werden, ohne die virtuelle Spalte verwenden zu müssen. Es gibt jedoch möglicherweise einige Design-Kompromisse, bei denen Sie keine Unterpartitionen erstellen müssen. In diesem Fall ist die virtuelle Spalte INPUT__FILE__NAME die beste Wahl.

Die Entscheidung zwischen den zwei Optionen:

Es hängt wirklich von Ihrem Anwendungsfall. Wenn Sie sich nie um die Dateien kümmern würden, die Sie aus der Hive-Tabelle ausschließen möchten, ist die Verwendung von Option 2 wahrscheinlich ein Overkill, und Sie sollten die Verzeichnisstruktur korrigieren und eine Hive-Tabelle über dem Verzeichnis erstellen, das Dateien enthält, die Ihnen wichtig sind .

Wenn die Dateien, die Sie derzeit ausschließen, dem gleichen Format wie die anderen Dateien folgen (also alle Teil derselben Hive-Tabelle sein können), könnten Sie eine Abfrage schreiben, die alle Daten im Verzeichnis analysiert. Dann geh mit Option 2.

+0

Danke Mark. Ich mache gerade Option 1 in der Produktion, aber ich werde Option 2 in meiner Dev-Umgebung testen, damit ich sie in meinem Toolbelt –

+0

für 'INPUT__FILE__NAME' hinzufügen kann. Immer noch müssen alle Daten gescannt werden, aber sie könnten trotzdem nützlich sein ... besonders wenn Sie nicht wollen/haben/nicht können – msciwoj

+0

Option # 2 ist immer noch ein Problem, wenn Sie einen INSERT OVERWRITE haben, wird es alle Dateien entfernen, auch wenn Sie wollen nur einen davon überschreiben. – Dhiraj