2015-07-17 16 views
7

Mi piacerebbe salvare i dati in un dataframe Spark (v 1.3.0) in una tabella Hive usando PySpark.salva Spark dataframe su Hive: tabella non leggibile perché "parquet not a SequenceFile"

I documentation stati:

"spark.sql.hive.convertMetastoreParquet: Quando è impostato su false, Spark SQL utilizzerà il Hive SerDe per tavoli in legno al posto del supporto integrato".

Guardando il Spark tutorial, è sembra che questa proprietà può essere impostata:

from pyspark.sql import HiveContext 

sqlContext = HiveContext(sc) 
sqlContext.sql("SET spark.sql.hive.convertMetastoreParquet=false") 

# code to create dataframe 

my_dataframe.saveAsTable("my_dataframe") 

Tuttavia, quando si tenta di interrogare la tabella salvata in Hive restituisce:

hive> select * from my_dataframe; 
OK 
Failed with exception java.io.IOException:java.io.IOException: 
hdfs://hadoop01.woolford.io:8020/user/hive/warehouse/my_dataframe/part-r-00001.parquet 
not a SequenceFile 

Come faccio a salvare la tabella in modo che sia immediatamente leggibile in Hive?

risposta

14

Sono stato lì ...
L'API è un po 'fuorviante su questo.
DataFrame.saveAsTablenon creare una tabella Hive, ma una origine tabella Spark interna.
Memorizza anche qualcosa in metastore Hive, ma non ciò che si intende.
Questo remark è stato creato dalla mailing list spark-user riguardante Spark 1.3.

Se si desidera creare una tabella Hive da Spark, è possibile utilizzare questo approccio:
1. Utilizzare Create Table ... via SparkSQL per Hive metastore.
2. Usare DataFrame.insertInto(tableName, overwriteMode) per i dati reali (Spark 1.3)

2

mi ha colpito questo problema la scorsa settimana ed è stato in grado di trovare una soluzione

Ecco la storia: posso vedere la tabella in Hive se ho creato la tavola senza partitionBy:

spark-shell>someDF.write.mode(SaveMode.Overwrite) 
        .format("parquet") 
        .saveAsTable("TBL_HIVE_IS_HAPPY") 

hive> desc TBL_HIVE_IS_HAPPY; 
     OK 
     user_id     string          
     email      string          
     ts      string          

Ma Hive non può capire lo schema della tabella (schema è vuoto ...) se faccio questo:

spark-shell>someDF.write.mode(SaveMode.Overwrite) 
        .format("parquet") 
        .saveAsTable("TBL_HIVE_IS_NOT_HAPPY") 

hive> desc TBL_HIVE_IS_NOT_HAPPY; 
     # col_name    data_type    from_deserializer 

[Soluzione]:

spark-shell>sqlContext.sql("SET spark.sql.hive.convertMetastoreParquet=false") 
spark-shell>df.write 
       .partitionBy("ts") 
       .mode(SaveMode.Overwrite) 
       .saveAsTable("Happy_HIVE")//Suppose this table is saved at /apps/hive/warehouse/Happy_HIVE 


hive> DROP TABLE IF EXISTS Happy_HIVE; 
hive> CREATE EXTERNAL TABLE Happy_HIVE (user_id string,email string,ts string) 
             PARTITIONED BY(day STRING) 
             STORED AS PARQUET 
             LOCATION '/apps/hive/warehouse/Happy_HIVE'; 
hive> MSCK REPAIR TABLE Happy_HIVE; 

Il problema è che la tabella origine dati creata attraverso dataframe API (+ partitionBy saveAsTable) non è compatibile con Hive (vedi questo link).. Impostando spark.sql.hive.convertMetastoreParquet su false come suggerito nello doc, Spark inserisce i dati solo su HDFS, ma non crea la tabella su Hive. Quindi è possibile passare manualmente alla shell di hive per creare una tabella esterna con la definizione della partizione dello schema corretta & che punta al percorso dei dati. Ho provato questo in Spark 1.6.1 e ha funzionato per me. Spero che aiuti!

+2

Hai pubblicato esattamente la stessa risposta [qui] (http://stackoverflow.com/questions/31341498/save-spark-dataframe-as-dynamic-partitioned-table-in-hive/37504196#37504196).se ritieni che la domanda sia duplice, devi contrassegnarla come tale e non pubblicare la stessa risposta due volte imo. – Jaap

+2

Sembra che il codice per TBL_HIVE_IS_NOT_HAPPY e TBL_HIVE_IS_HAPPY sia esattamente lo stesso. Mi sto perdendo qualcosa? –

Problemi correlati