Est-il possible de sauvegarder DataFrame
dans spark directement dans Hive.
J'ai essayé de convertir DataFrame
en Rdd
, puis de l'enregistrer sous forme de fichier texte, puis de le charger dans Hive. Mais je me demande si je peux directement sauver dataframe
à Hive
Si vous utilisez saveAsTable (c'est plutôt comme si vous persistiez dans votre dataframe), vous devez vous assurer que vous avez assez de mémoire allouée à votre application spark. Pour les grands ensembles de données, vous pouvez créer une table temporaire et la vider dans la table Hive.
Vous pouvez utiliser l'objet sqlContext disponible dans spark.
Disons que votre trame de données est myDf. Vous pouvez créer une table temporaire.
myDf.createOrReplaceTempView("mytempTable")
Vous pouvez ensuite utiliser une simple instruction Hive pour créer une table et vider les données de votre table temporaire.
sqlContext.sql("create table mytable as select * from mytempTable");
Utilisez DataFrameWriter.saveAsTable
. (df.write.saveAsTable(...)
) Voir Guide Spark SQL et DataFrame .
df.write.saveAsTable(...)
n'est pas obsolète dans la documentation de Spark 2.0. Cela a fonctionné pour nous sur Amazon EMR. Nous avons parfaitement réussi à lire les données de S3 dans un cadre de données, à les traiter, à créer un tableau à partir du résultat et à le lire avec MicroStrategy . La réponse de Vinays a également fonctionné.
vous devez avoir/créer un contexte de ruche
import org.Apache.spark.sql.Hive.HiveContext;
HiveContext sqlContext = new org.Apache.spark.sql.Hive.HiveContext(sc.sc());
Ensuite, sauvegardez directement dataframe ou sélectionnez les colonnes à stocker en tant que table Hive
df est dataframe
df.write().mode("overwrite").saveAsTable("schemaName.tableName");
ou
df.select(df.col("col1"),df.col("col2"), df.col("col3")) .write().mode("overwrite").saveAsTable("schemaName.tableName");
ou
df.write().mode(SaveMode.Overwrite).saveAsTable("dbName.tableName");
SaveModes sont Append/Ignore/Overwrite/ErrorIfExists
J'ai ajouté ici la définition de HiveContext de Spark Documentation,
En plus du SQLContext de base, vous pouvez également créer un HiveContext, qui fournit un sur-ensemble des fonctionnalités fournies par le SQLContext de base. Des fonctionnalités supplémentaires incluent la possibilité d'écrire des requêtes à l'aide de l'analyseur plus complet HiveQL, l'accès aux fichiers UDF Hive et la possibilité de lire des données à partir de tables Hive. Pour utiliser un contexte Hive, vous n'avez pas besoin d'une configuration Hive existante, et toutes les sources de données disponibles pour un SQLContext sont toujours disponibles. HiveContext est uniquement emballé séparément afin d'éviter d'inclure toutes les dépendances de Hive dans la génération Spark par défaut.
sur Spark version 1.6.2, l'utilisation de "dbName.tableName" génère cette erreur:
org.Apache.spark.sql.AnalysisException: la spécification du nom de la base de données ou d'autres qualificatifs ne sont pas autorisés pour les tables temporaires. Si le nom de la table contient des points (.), Veuillez citer le nom de la table avec des backticks () .`
Enregistrer dans Hive consiste simplement à utiliser la méthode write()
de votre SQLContext:
df.write.saveAsTable(tableName)
Depuis Spark 2.2: utilisez DataSet à la place de DataFrame.
Voici la version de PySpark pour créer une table Hive à partir d'un fichier de parquet. Vous avez peut-être généré des fichiers Parquet à l'aide d'un schéma inféré et souhaitez maintenant transmettre la définition au métastore Hive. Vous pouvez également transmettre la définition au système comme AWS Glue ou AWS Athena et pas seulement à Hive metastore. Ici, j'utilise spark.sql pour pousser/créer une table permanente.
# Location where my parquet files are present.
df = spark.read.parquet("s3://my-location/data/")
cols = df.dtypes
buf = []
buf.append('CREATE EXTERNAL TABLE test123 (')
keyanddatatypes = df.dtypes
sizeof = len(df.dtypes)
print ("size----------",sizeof)
count=1;
for eachvalue in keyanddatatypes:
print count,sizeof,eachvalue
if count == sizeof:
total = str(eachvalue[0])+str(' ')+str(eachvalue[1])
else:
total = str(eachvalue[0]) + str(' ') + str(eachvalue[1]) + str(',')
buf.append(total)
count = count + 1
buf.append(' )')
buf.append(' STORED as parquet ')
buf.append("LOCATION")
buf.append("'")
buf.append('s3://my-location/data/')
buf.append("'")
buf.append("'")
##partition by pt
tabledef = ''.join(buf)
print "---------print definition ---------"
print tabledef
## create a table using spark.sql. Assuming you are using spark 2.1+
spark.sql(tabledef);
Pour les tables externes Hive, j'utilise cette fonction dans PySpark:
def save_table(sparkSession, dataframe, database, table_name, save_format="PARQUET"):
print("Saving result in {}.{}".format(database, table_name))
output_schema = "," \
.join(["{} {}".format(x.name.lower(), x.dataType) for x in list(dataframe.schema)]) \
.replace("StringType", "STRING") \
.replace("IntegerType", "INT") \
.replace("DateType", "DATE") \
.replace("LongType", "INT") \
.replace("TimestampType", "INT") \
.replace("BooleanType", "BOOLEAN") \
.replace("FloatType", "FLOAT")\
.replace("DoubleType","FLOAT")
output_schema = re.sub(r'DecimalType[(][0-9]+,[0-9]+[)]', 'FLOAT', output_schema)
sparkSession.sql("DROP TABLE IF EXISTS {}.{}".format(database, table_name))
query = "CREATE EXTERNAL TABLE IF NOT EXISTS {}.{} ({}) STORED AS {} LOCATION '/user/Hive/{}/{}'" \
.format(database, table_name, output_schema, save_format, database, table_name)
sparkSession.sql(query)
dataframe.write.insertInto('{}.{}'.format(database, table_name),overwrite = True)