J'aimerais enregistrer les données d'une structure de données Spark (v 1.3.0) dans une table Hive à l'aide de PySpark.
La documentation indique:
"spark.sql.Hive.convertMetastoreParquet: Lorsqu'il est défini sur false, Spark SQL utilise Hive SerDe pour les tables de parquet au lieu du support intégré."
En regardant le didacticiel Spark , il semble que cette propriété puisse être définie:
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")
Cependant, lorsque j'essaie d'interroger la table enregistrée dans Hive, elle renvoie:
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
Comment enregistrer la table afin qu'elle soit immédiatement lisible dans Hive?
J'ai été là...
L'API est un peu trompeur sur celui-ci.DataFrame.saveAsTable
fait not crée une table Hive, mais une source de table Spark interne.
Il stocke également quelque chose dans Hive metastore, mais pas ce que vous souhaitez.
Cette remarque a été faite par la liste de diffusion spark-user concernant Spark 1.3.
Si vous souhaitez créer une table Hive à partir de Spark, vous pouvez utiliser cette approche:
1. Utilisez Create Table ...
via SparkSQL pour le métastore.
2. Utilisez DataFrame.insertInto(tableName, overwriteMode)
pour les données réelles (Spark 1.3)
J'ai frappé ce problème la semaine dernière et j'ai pu trouver une solution de contournement
Voici l'histoire: Je peux voir la table dans Hive si j'ai créé la table sans 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
Mais Hive ne comprend pas le schéma de la table (le schéma est vide ...) si je fais ceci:
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
[Solution]:
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;
Le problème est que la table de source de données créée via l'API Dataframe (partitionBy + saveAsTable) n'est pas compatible avec Hive (voir this link ). En définissant spark.sql.Hive.convertMetastoreParquet sur false comme suggéré dans le fichier doc , Spark ne place les données que sur HDFS, mais ne crée pas de table sur Hive. Et ensuite, vous pouvez manuellement accéder à Hive Shell pour créer une table externe avec la définition correcte du schéma et de la partition pointant vers l'emplacement des données. Je l'ai testé dans Spark 1.6.1 et cela a fonctionné pour moi. J'espère que ça aide!
J'ai fait dans pyspark, version 2.3.0:
crée une table vide sur laquelle nous devons sauvegarder/écraser des données telles que:
create table databaseName.NewTableName like databaseName.OldTableName;
puis lancez la commande ci-dessous:
df1.write.mode("overwrite").partitionBy("year","month","day").format("parquet").saveAsTable("databaseName.NewTableName");
Le problème est que vous ne pouvez pas lire ce tableau avec Hive, mais que vous pouvez lire avec étincelle.