web-dev-qa-db-ja.com

保存SparkデータフレームをHiveに:「寄木細工はSequenceFileではない」ためテーブルを読み取れません

PySparkを使用して、データをSpark(v 1.3.0)データフレームのHiveテーブルに保存したいと思います。

ドキュメント の状態:

"spark.sql.Hive.convertMetastoreParquet:falseに設定すると、Spark SQLは、組み込みのサポートではなく、寄木細工のテーブルにHiveSerDeを使用します。"

Sparkチュートリアル を見ると、このプロパティを設定できるようです。

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")

ただし、Hiveに保存されたテーブルをクエリしようとすると、次のように返されます。

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

テーブルを保存して、Hiveですぐに読み取れるようにするにはどうすればよいですか?

9
Alex Woolford

私はそこに行ったことがある...
APIはこれに関してちょっと誤解を招きます。
_DataFrame.saveAsTable_はnotHiveテーブルを作成しますが、内部Sparkテーブルソース。
Hiveメタストアにも何かを保存しますが、意図したものではありません。
この 備考 はSpark 1.3に関してspark-userメーリングリストによって作成されました。

SparkからHiveテーブルを作成する場合は、次の方法を使用できます。
1。 SparkSQL for Hiveメタストアを介して_Create Table ..._を使用します。
2。実際のデータにはDataFrame.insertInto(tableName, overwriteMode)を使用します(Spark 1.3)

16
Leet-Falcon

私は先週この問題にぶつかり、回避策を見つけることができました

ストーリーは次のとおりです。partitionByなしでテーブルを作成した場合、Hiveでテーブルを確認できます。

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                                      

しかし、これを行うと、Hiveはテーブルスキーマを理解できません(スキーマは空です...)。

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  

[ソリューション]

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;

問題は、Dataframe API(partitionBy + saveAsTable)を介して作成されたデータソーステーブルがHiveと互換性がないことです(これを参照 リンク )。 doc で提案されているようにspark.sql.Hive.convertMetastoreParquetをfalseに設定すると、SparkはデータをHDFSに配置するだけで、Hiveにテーブルを作成しません。 。次に、手動でHive Shellに移動して、データの場所を指す適切なスキーマとパーティションの定義を持つ外部テーブルを作成できます。 Spark 1.6.1でこれをテストしましたが、うまくいきました。これがお役に立てば幸いです。

3
Yuan Zhao

enter image description here

enter image description here

メタデータはまだ存在していません。つまり、HDFSには存在するがメタストアには存在しないパーティションを、Hiveメタストアに追加します。

0
Tutu Kumari

私はpysparkで行いました、sparkバージョン2.3.0:

次のようにデータを保存/上書きする必要がある空のテーブルを作成します。

create table databaseName.NewTableName like databaseName.OldTableName;

次に、以下のコマンドを実行します。

df1.write.mode("overwrite").partitionBy("year","month","day").format("parquet").saveAsTable("databaseName.NewTableName");

問題は、この表をHiveで読み取ることはできませんが、sparkで読み取ることができることです。

0
dinesh rajput