DataFrameをHiveに直接保存する方法は?


85

DataFrameSparkをHiveに直接保存することは可能ですか?

変換してDataFrameからRddテキストファイルとして保存してから、ハイブにロードしてみました。しかし、私は直接dataframeハイブに保存できるかどうか疑問に思っています

回答:


118

sqlContextを使用して、メモリ内の一時テーブルを作成し、それらをハイブテーブルに格納できます。

データフレームがmyDfだとしましょう。を使用して1つの一時テーブルを作成できます。

myDf.createOrReplaceTempView("mytempTable") 

次に、単純なハイブステートメントを使用してテーブルを作成し、一時テーブルからデータをダンプできます。

sqlContext.sql("create table mytable as select * from mytempTable");

2
これにより、spark 2.0でwrite.saveAsTableを使用したときに発生した寄木細工の読み取りエラーが回避されました
ski_squaw 2016年

2
はい。ただし、一時テーブルを作成する前に、データフレームでpartitionbyを使用できます。@chhantyal
ビナイクマール

1
どのようにしてtemporaryテーブルをテーブルと組み合わせることができましたhiveか?それを行うとき、show tablesそれはhive私のspark 2.3.0インストールのためのテーブルだけを含みます
StephenBoesch 2017年

1
この一時テーブルはハイブコンテキストに保存され、ハイブテーブルには一切属しません。
ビナイクマール2017年

1
こんにちは@VinayKumar「saveAsTable(データフレームの永続化に似ています)を使用している場合は、sparkアプリケーションに十分なメモリが割り当てられていることを確認する必要があります」と言う理由。この点を説明してもらえますか?
enneppi 2018

28

を使用しDataFrameWriter.saveAsTableます。(df.write.saveAsTable(...)SparkSQLおよびDataFrameガイドを参照してください。


4
saveAsTableは、Hive互換のテーブルを作成しません。私が見つけた最良の解決策は、VinayKumarです。
RChat 2016

@Jacek:私の答えが間違っていると思うので、私はこのメモを自分で追加しました。受け入れられることを除いて、私はそれを削除します。メモが間違っていると思いますか?
ダニエルダラボス2016

はい。メモが間違っていたので、削除しました。「私が間違っている場合は訂正してください」がここに適用されます:)
Jacek Laskowski 2016

1
これdf.write().saveAsTable(tableName) はストリーミングデータもテーブルに書き込みますか?
user1870400 2017

1
いいえ、saveAsTableを使用してストリーミングデータを保存することはできません。APIにも含まれていません
Brian

21

df.write.saveAsTable(...)Spark2.0のドキュメントで非推奨とは見なされません。それはAmazonEMRで私たちのために働いています。S3からデータフレームにデータを読み取り、処理し、結果からテーブルを作成して、MicroStrategyで読み取ることができました。Vinaysの答えもうまくいきました。


5
誰かがこの回答を長さと内容のために低品質としてフラグを立てました。正直なところ、コメントとしてはもっと良かったでしょう。2年経ちましたが、役に立ったと思っている方もいらっしゃると思いますので、そのままにしておくといいのではないでしょうか。
serakfalcon 2018年

私は同意します、コメントはより良い選択だったでしょう。学んだ教訓:
Alex

15

HiveContextを持っている/作成する必要があります

import org.apache.spark.sql.hive.HiveContext;

HiveContext sqlContext = new org.apache.spark.sql.hive.HiveContext(sc.sc());

次に、データフレームを直接保存するか、ハイブテーブルとして保存する列を選択します

dfはデータフレームです

df.write().mode("overwrite").saveAsTable("schemaName.tableName");

または

df.select(df.col("col1"),df.col("col2"), df.col("col3")) .write().mode("overwrite").saveAsTable("schemaName.tableName");

または

df.write().mode(SaveMode.Overwrite).saveAsTable("dbName.tableName");

SaveModesはAppend / Ignore / Overwrite / ErrorIfExistsです

ここに、SparkドキュメントからHiveContextの定義を追加しました。

基本的なSQLContextに加えて、基本的なSQLContextによって提供される機能のスーパーセットを提供するHiveContextを作成することもできます。追加機能には、より完全なHiveQLパーサーを使用してクエリを作成する機能、Hive UDFへのアクセス、およびHiveテーブルからデータを読み取る機能が含まれます。HiveContextを使用するために、既存のHiveセットアップを用意する必要はなく、SQLContextで使用可能なすべてのデータソースを引き続き使用できます。HiveContextは、デフォルトのSparkビルドにHiveのすべての依存関係が含まれないようにするために、個別にパッケージ化されているだけです。


Sparkバージョン1.6.2では、「dbName.tableName」を使用すると次のエラーが発生します。

org.apache.spark.sql.AnalysisException:データベース名またはその他の修飾子を一時テーブルに指定することはできません。テーブル名にドット(。)が含まれている場合は、テーブル名をバッククォート()で引用してください。


2番目のコマンドは次のとおりです。'df.select(df.col( "col1")、df.col( "col2")、df.col( "col3"))。write()。mode( "overwrite")。saveAsTable ( "schemaName.tableName"); ' 上書きする予定の選択した列がテーブルにすでに存在している必要がありますか?つまり、既存のテーブルがあり、既存の列1、2、3をsparkのdfからの新しいデータで上書きするだけですか?それは正しく解釈されていますか?
dieHellste 2016

3
df.write().mode...次のように変更する必要がありますdf.write.mode...
ユーザー923227 2018

8

Hiveに保存するにwrite()は、SQLContextのメソッドを使用するだけです。

df.write.saveAsTable(tableName)

https://spark.apache.org/docs/2.1.0/api/java/org/apache/spark/sql/DataFrameWriter.html#saveAsTable(java.lang.String)を参照してください

Spark 2.2以降:DataFrameの代わりにDataSetを使用します。


ジョブが中止されたことを示すエラーがあるようです。次のコードを試しましたpyspark_df.write.mode( "overwrite")。saveAsTable( "InjuryTab2")
Sade

こんにちは!なぜこれ?From Spark 2.2: use DataSet instead DataFrame.
onofricamila

3

投稿に遅れて書いて申し訳ありませんが、受け入れられた回答がありません。

df.write().saveAsTableスローされAnalysisException、HIVEテーブルと互換性がありません。

DFを保存df.write().format("hive")するのがコツです!

しかし、それがうまくいかない場合は、前のコメントと回答を参考にしてください。これが私の意見では最善の解決策です(ただし、提案は受け付けています)。

最善のアプローチは、HIVEテーブル(PARTITIONEDテーブルを含む)を明示的に作成することです。

def createHiveTable: Unit ={
spark.sql("CREATE TABLE $hive_table_name($fields) " +
  "PARTITIONED BY ($partition_column String) STORED AS $StorageType")
}

DFを一時テーブルとして保存します。

df.createOrReplaceTempView("$tempTableName")

PARTITIONEDHIVEテーブルに挿入します。

spark.sql("insert into table default.$hive_table_name PARTITION($partition_column) select * from $tempTableName")
spark.sql("select * from default.$hive_table_name").show(1000,false)

オフコースDFの最後の列パーティション列になるので、それに応じてHIVEテーブルを作成してください!

うまくいったらコメントしてください!か否か。


- 更新 -

df.write()
  .partitionBy("$partition_column")
  .format("hive")
  .mode(SaveMode.append)
  .saveAsTable($new_table_name_to_be_created_in_hive)  //Table should not exist OR should be a PARTITIONED table in HIVE

1

これは、寄木細工のファイルからHiveテーブルを作成するためのPySparkバージョンです。推測されたスキーマを使用してParquetファイルを生成し、定義をHiveメタストアにプッシュしたい場合があります。Hiveメタストアだけでなく、AWSGlueやAWSAthenaなどのシステムに定義をプッシュすることもできます。ここでは、spark.sqlを使用して永続テーブルをプッシュ/作成しています。

   # 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);

1

Hive外部テーブルの場合、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)

1

私の場合、これは問題なく機能します。

from pyspark_llap import HiveWarehouseSession
hive = HiveWarehouseSession.session(spark).build()
hive.setDatabase("DatabaseName")
df = spark.read.format("csv").option("Header",True).load("/user/csvlocation.csv")
df.write.format(HiveWarehouseSession().HIVE_WAREHOUSE_CONNECTOR).option("table",<tablename>).save()

完了!!

あなたはデータを読むことができます、あなたは「従業員」として与えることができます

hive.executeQuery("select * from Employee").show()

詳細については、次のURLを使用してくださいhttps//docs.cloudera.com/HDPDocuments/HDP3/HDP-3.1.5/integrating-hive/content/hive-read-write-operations.html


0

このようなHortonworksspark -llapライブラリを使用できます

import com.hortonworks.hwc.HiveWarehouseSession

df.write
  .format("com.hortonworks.spark.sql.hive.llap.HiveWarehouseConnector")
  .mode("append")
  .option("table", "myDatabase.myTable")
  .save()

-1

データフレームからハイブテーブル(存在しない)作成したい場合(で作成に失敗する場合がありますDataFrameWriter.saveAsTable)。StructType.toDDL列を文字列としてリストするのに役立ちます。

val df = ...

val schemaStr = df.schema.toDDL # This gives the columns 
spark.sql(s"""create table hive_table ( ${schemaStr})""")

//Now write the dataframe to the table
df.write.saveAsTable("hive_table")

hive_tableでデータベースを提供しなかったため、デフォルトのスペースに作成されますspark.sql()。データベースでのstg.hive_table作成hive_tableに使用できstgます。


詳細な例は、こちらをご覧ください:stackoverflow.com/a/56833395/1592191
mrsrinivas
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.