web-dev-qa-db-fra.com

Comment enregistrer DataFrame directement dans Hive?

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

49
Gourav

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");
75
Vinay Kumar

Utilisez DataFrameWriter.saveAsTable . (df.write.saveAsTable(...)) Voir Guide Spark SQL et DataFrame .

16
Daniel Darabos

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é.

13
Alex

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 () .`

11
Anandkumar

Enregistrer dans Hive consiste simplement à utiliser la méthode write() de votre SQLContext:

df.write.saveAsTable(tableName)

Voir https://spark.Apache.org/docs/2.1.0/api/Java/org/Apache/spark/sql/DataFrameWriter.html#saveAsTable(Java.lang.String)

Depuis Spark 2.2: utilisez DataSet à la place de DataFrame.

3

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);
0
kartik

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)
0
Shadowtrooper