2015-07-17 5 views
7

Я хотел бы сохранить данные в фрейме Spark (v 1.3.0) в таблицу Hive с помощью PySpark.save Spark dataframe to Hive: таблица не читается, потому что «паркет не SequenceFile»

В documentation состояния:

«spark.sql.hive.convertMetastoreParquet: Если установлено значение ложно, Свечи SQL будет использовать улей SerDe для паркетных таблиц вместо встроенной поддержки.»

Глядя на Spark tutorial, это, кажется, что это свойство может быть установлено:

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> 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?

ответ

14

Я был там ...
API является своего рода вводящим в заблуждение.
DataFrame.saveAsTableне создать таблицу улей, а внутренний источник искры таблицы.
Он также хранит что-то в метафоре улья, но не то, что вы намереваетесь.
Этот remark был составлен списком рассылки spark-user относительно Spark 1.3.

Если вы хотите создать улую таблицу из искры, вы можете использовать этот подход:
1. Используйте Create Table ... через SparkSQL для улья metastore.
2. Использование DataFrame.insertInto(tableName, overwriteMode) для фактических данных (Спарк 1.3)

2

Я ударил этот вопрос на прошлой неделе и был в состоянии найти обходной путь

Вот история: я могу увидеть таблицу в улей, если я создал стол без partitionBy:

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          

Но улей не может понять схему таблицы (схемы пусто ...), если я это сделать:

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) не совместим с улья (см это link).. Установив spark.sql.hive.convertMetastoreParquet на false, как предлагается в doc, Spark только помещает данные в HDFS, но не создает таблицу на Hive. И затем вы можете вручную перейти в оболочку улья, чтобы создать внешнюю таблицу с правильной схемой определения раздела &, указывающей на местоположение данных. Я тестировал это в Spark 1.6.1, и это сработало для меня. Надеюсь, это поможет!

+2

Вы отправили точно такой же ответ [здесь] (http://stackoverflow.com/questions/31341498/save-spark-dataframe-as-dynamic-partitioned-table-in-hive/37504196#37504196).если вы считаете, что вопрос является дубликатом, вы должны отметить его как таковой, а не повторять один и тот же ответ дважды. – Jaap

+2

Похоже, что код для TBL_HIVE_IS_NOT_HAPPY и TBL_HIVE_IS_HAPPY, точно такой же. Я что-то упускаю? –

Смежные вопросы