2013-04-01 15 views
37

Sto utilizzando la versione di Hive di Cloudera e sto provando a creare una tabella esterna su un file csv che contiene i nomi di colonna nella prima colonna. Ecco il codice che sto usando per farlo.Tabella esterna alveare Salta la prima riga

CREATE EXTERNAL TABLE Test ( 
    RecordId int, 
    FirstName string, 
    LastName string 
) 
ROW FORMAT serde 'com.bizo.hive.serde.csv.CSVSerde' 
WITH SerDeProperties ( 
    "separatorChar" = "," 
) 
STORED AS TEXTFILE 
LOCATION '/user/File.csv' 

dati di esempio

RecordId,FirstName,LastName 
1,"John","Doe" 
2,"Jane","Doe" 

Qualcuno mi può aiutare con il modo di saltare la prima riga o devo aggiungere una tappa intermedia?

+0

Ho appena iniziato a giocare con Hive me stesso e da quello che posso dire, il lavoro di SerDe solo su una base riga per riga, quindi potrebbe non essere possibile senza qualche intermedia. Se riesco a pensare a qualcosa, lo posterò qui. Sono anche interessato a una soluzione. – nolanpro

risposta

49

Le righe di intestazione nei dati sono un mal di testa perpetuo in Hive. A parte modificare la fonte Hive, credo che non puoi andartene senza un passaggio intermedio. (Modifica: Questo non è più vero, vedi aggiornamento sotto)

Sfortunatamente, questo risponde alla tua domanda. Fornirò alcune idee per il passaggio intermedio per completezza.

È possibile allontanarsi senza un ulteriore passaggio nel carico di dati se si è disposti a filtrare la riga di intestazione su ogni query che tocca la tabella. Sfortunatamente questo aggiunge un set extra praticamente ovunque. E dovrai essere intelligente/disordinato quando la riga dell'intestazione viola lo schema. Se segui questo approccio, potresti prendere in considerazione la scrittura di un SerDe personalizzato che facilita il filtraggio di questa riga. Sfortunatamente, SerDe non può rimuovere completamente la riga (o potrebbe formare una possibile soluzione), devono restituire qualcosa come null. Non ho mai visto questo approccio preso in pratica per gestire i file di intestazione poiché rende la lettura di un dolore, e la lettura tende ad essere molto più comune della scrittura. Potrebbe avere un posto se si ha a che fare con una di tabelle o se la riga di intestazione è solo una riga tra molte righe malformate.

Si potrebbe fare questo filtraggio una volta con variazioni sull'eliminazione di quella prima riga nel caricamento dei dati. Una clausola WHERE in una dichiarazione INSERT lo farebbe. Potresti usare utility come sed per sbarazzartene. Ho visto entrambi gli approcci adottati. Ci sono dei trade-off tra i quali si prende l'approccio e nessuno dei due è l'unico vero modo per gestire le righe di intestazione. Sfortunatamente, entrambi questi approcci richiedono tempo e richiedono una duplicazione temporanea dei dati. Se hai assolutamente bisogno della riga di intestazione per un'altra applicazione, la duplicazione sarebbe permanente.

Aggiornamento:

Da Hive v0.13.0, è possibile utilizzare skip.header.line.count. Puoi anche specificare lo stesso durante la creazione della tabella. Ad esempio:

create external table testtable (name string, message string) 
row format delimited 
fields terminated by '\t' 
lines terminated by '\n' 
location '/testtable' 
tblproperties ("skip.header.line.count"="1"); 
+11

Sembra che ora puoi usare "SET skip.header.line.count = 1;" saltare la riga dell'intestazione. Per ulteriori informazioni consultare le note di patch al [https://issues.apache.org/jira/browse/HIVE-5795](https://issues.apache.org/jira/browse/HIVE-5795). –

+0

Grazie per l'aggiornamento molto utile! Al momento non sto lavorando con Hive per rimanere aggiornato su modifiche come questa. Ho fatto il palo un wiki comunità, quindi se avete testato SET skip.header.line.count sarei grato se volesse fissare la mia risposta (anche se lasciare nelle soluzioni alternative per le persone sulle versioni di sotto 0.13.0 per un po ') . –

1

Non sono abbastanza sicuro se funziona con ROW FORMAT serde 'com.bizo.hive.serde.csv.CSVSerde' ma suppongo che dovrebbe essere simile a ROW FORMAT DELIMITED FIELDS TERMINATED BY ','.
Nel tuo caso la prima riga verrà trattata come una riga normale. Ma il primo campo non riesce ad essere INT, quindi tutti i campi, per la prima riga, saranno impostati come NULL. È necessario solo un passo intermedio per risolvere il problema:

INSERT OVERWRITE TABLE Test 
SELECT * from Test WHERE RecordId IS NOT NULL 

Solo uno svantaggio è che il file CSV originale verrà modificato. Spero possa essere d'aiuto. GL!

+0

CSVSerDe viene utilizzato per eliminare le virgolette nel file CSV. –

1

Ho anche faticato con questo e non ho trovato alcun modo di dire all'hive di saltare la prima riga, come ad esempio c'è ad es. in Greenplum. Quindi alla fine ho dovuto rimuoverlo dai file. ad es. "cat File.csv | grep -v RecordId> File_no_header.csv"

1
create external table table_name( 
Year int, 
Month int, 
column_name data_type) 
row format delimited fields terminated by ',' 
location '/user/user_name/example_data' TBLPROPERTIES('serialization.null.format'='', 'skip.header.line.count'='1'); 
0

opere skip.header.line.count ma se avete qualche strumento esterno accedendo Accedendo a questo tavolo, sarà ancora vedere che i dati effettivi senza saltare quelle linee

8

Mentre avete la vostra risposta da Daniel, qui ci sono alcune personalizzazioni possibili utilizzando OpenCSVSerde:

CREATE EXTERNAL TABLE `mydb`.`mytable`(
    `product_name` string, 
    `brand_id` string, 
    `brand` string, 
    `color` string, 
    `description` string, 
    `sale_price` string) 
PARTITIONED BY (
    `seller_id` string) 
ROW FORMAT SERDE 
    'org.apache.hadoop.hive.serde2.OpenCSVSerde' 
WITH SERDEPROPERTIES (
    'separatorChar' = '\t', 
    'quoteChar' = '"', 
    'escapeChar' = '\\') 
STORED AS INPUTFORMAT 
    'org.apache.hadoop.mapred.TextInputFormat' 
OUTPUTFORMAT 
    'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat' 
LOCATION 
    'hdfs://namenode.com:port/data/mydb/mytable' 
TBLPROPERTIES (
    'serialization.null.format' = '', 
    'skip.header.line.count' = '1') 

Con questo, si ha il controllo totale sul separatore di carattere preventivo, fuga carattere, la gestione e la manipolazione nulla intestazione

.

Guarda here e here.

+0

venuti qui alla ricerca di questa risposta, perché sto utilizzando AWS Athena, che mi obbliga a usare OpenCSVSerde. Non ho toccato nulla con HIVE per un po ', ma dal momento che questo SerDe proviene dallo stack HIVE, è bello vedere questa risposta secondaria su OpenCSVSerde. Grazie @Nirmal –

+1

Una nota importante: l'ho scoperto nelle documentazioni SerDe. * * Limitazione Questo SerDe tratta tutte le colonne di essere di tipo stringa. Anche se si crea una tabella con tipi di colonne non stringa utilizzando questo SerDe, l'output TABELLA DESCRIBE mostrerà il tipo di colonna stringa. Le informazioni sul tipo sono recuperate dal SerDe. Per convertire colonne nel tipo desiderato in una tabella , è possibile creare una vista sulla tabella che esegue il CAST sul tipo desiderato . –

1

basta aggiungere sotto proprietà nella query e la prima riga di intestazione o int il record non si caricare o verrà saltato.

Prova questa

tblproperties ("skip.header.line.count"="1"); 
+1

Non che questa soluzione sia inclusa anche nella risposta principale :-) – Carpetsmoker

Problemi correlati