2015-07-17 16 views
7

Tôi muốn lưu dữ liệu trong khung dữ liệu Spark (v 1.3.0) vào bảng Hive bằng PySpark.lưu khung dữ liệu Spark vào Hive: bảng không thể đọc được vì "sàn gỗ không phải là SequenceFile"

Các documentation trạng thái:

"spark.sql.hive.convertMetastoreParquet: Khi đặt sai, Spark SQL sẽ sử dụng Hive SerDe cho các bảng gỗ thay vì xây dựng trong hỗ trợ."

Nhìn vào Spark tutorial, là dường như rằng thuộc tính này có thể được thiết lập:

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

Tuy nhiên, khi tôi cố gắng để truy vấn bảng lưu trong Hive nó sẽ trả về:

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 

thế nào thế nào để tôi lưu bảng để nó ngay lập tức có thể đọc được trong Hive?

Trả lời

14

Tôi đã ở đó ...
API có thể gây hiểu nhầm về điều này.
DataFrame.saveAsTable không không tạo bảng Hive, nhưng là nguồn bảng Spark nội bộ.
Nó cũng lưu trữ một cái gì đó vào di tích Hive, nhưng không phải những gì bạn có ý định.
remark này được tạo bởi danh sách gửi thư của người dùng spark liên quan đến Spark 1.3.

Nếu bạn muốn tạo bảng Hive từ Spark, bạn có thể sử dụng phương pháp này:
1. Sử dụng Create Table ... qua SparkSQL cho di tích Hive.
2. Sử dụng DataFrame.insertInto(tableName, overwriteMode) cho dữ liệu thực tế (Spark 1.3)

2

tôi nhấn vấn đề này vào tuần trước và đã có thể tìm thấy một workaround

Dưới đây là những câu chuyện: tôi có thể thấy bảng trong Hive nếu tôi tạo ra bảng mà không 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          

Nhưng Hive không thể hiểu được sơ đồ bảng (schema là trống rỗng ...) nếu tôi làm điều này:

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 

[Giải pháp]:

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; 

Vấn đề là bảng nguồn dữ liệu được tạo ra thông qua Dataframe API (partitionBy + saveAsTable) là không tương thích với Hive (xem này link).. Bằng cách đặt spark.sql.hive.convertMetastoreParquet thành sai như đề xuất trong doc, Spark chỉ đặt dữ liệu lên HDFS, nhưng sẽ không tạo bảng trên Hive. Và sau đó bạn có thể tự đi vào vỏ hive để tạo ra một bảng bên ngoài với lược đồ thích hợp & định nghĩa phân vùng trỏ đến vị trí dữ liệu. Tôi đã thử nghiệm điều này trong Spark 1.6.1 và nó đã làm việc cho tôi. Tôi hi vọng cái này giúp được!

+2

Bạn đã đăng chính xác câu trả lời tương tự [tại đây] (http://stackoverflow.com/questions/31341498/save-spark-dataframe-as-dynamic-partitioned-table-in-hive/37504196#37504196).nếu bạn nghĩ rằng câu hỏi là một bản sao, bạn nên đánh dấu nó như vậy và không đăng cùng một câu trả lời hai lần imo. – Jaap

+2

Dường như mã cho TBL_HIVE_IS_NOT_HAPPY và TBL_HIVE_IS_HAPPY, giống hệt nhau. Tui bỏ lỡ điều gì vậy? –

Các vấn đề liên quan