web-dev-qa-db-ja.com

Spark SQL saveAsTableは、パーティションが指定されている場合、Hiveと互換性がありません

エッジケースの種類、パーケットテーブルをSpark SQL with partition、

#schema definitioin
final StructType schema = DataTypes.createStructType(Arrays.asList(
    DataTypes.createStructField("time", DataTypes.StringType, true),
    DataTypes.createStructField("accountId", DataTypes.StringType, true),
    ...

DataFrame df = hiveContext.read().schema(schema).json(stringJavaRDD);

df.coalesce(1)
    .write()
    .mode(SaveMode.Append)
    .format("parquet")
    .partitionBy("year")
    .saveAsTable("tblclick8partitioned");

スパーク警告:

Spark SQL固有の形式でHiveメタストアにパーティション化されたデータソース関係を永続化します。これはHiveと互換性がありません。

Hive内:

Hive> describe tblclick8partitioned;
OK
col                     array<string>           from deserializer
Time taken: 0.04 seconds, Fetched: 1 row(s)

明らかにスキーマは正しくありません。ただし、Spark SQLでsaveAsTableを使用すると、問題なくテーブルをクエリできます。

質問は、Spark SQLにパーティション情報を含むHiveと互換性のあるSQLで寄木細工のテーブルを作成するにはどうすればよいですか?

12
dunlu_98k

これは、DataFrame.saveAsTableがRDDパーティションを作成し、Hiveパーティションを作成しないためです。回避策は、DataFrame.saveAsTableを呼び出す前にhqlを介してテーブルを作成することです。 SPARK-14927 の例は次のようになります。

hc.sql("create external table tmp.partitiontest1(val string) partitioned by (year int)")

Seq(2012 -> "a", 2013 -> "b", 2014 -> "c").toDF("year", "val")
  .write
  .partitionBy("year")
  .mode(SaveMode.Append)
  .saveAsTable("tmp.partitiontest1")
10
rys

解決策は、Hiveでテーブルを作成し、...partitionBy("year").insertInto("default.mytable")でデータを保存することです。

私の経験では、Hiveでテーブルを作成してから...partitionBy("year").saveAsTable("default.mytable")を使用しても機能しませんでした。これはSpark 1.6.2です。

1
foghorn