Làm cách nào để lưu DataFrame trực tiếp vào Hive?


85

Có thể lưu DataFrametrong spark trực tiếp vào Hive không?

Tôi đã thử chuyển đổi DataFramesang Rddrồi lưu dưới dạng tệp văn bản rồi tải trong tổ ong. Nhưng tôi đang phân vân không biết tôi có thể trực tiếp tiết kiệm dataframeđể làm tổ ong được không

Câu trả lời:


116

Bạn có thể tạo một bảng tạm thời trong bộ nhớ và lưu trữ chúng trong bảng hive bằng sqlContext.

Giả sử khung dữ liệu của bạn là myDf. Bạn có thể tạo một bảng tạm thời bằng cách sử dụng

myDf.createOrReplaceTempView("mytempTable") 

Sau đó, bạn có thể sử dụng một câu lệnh hive đơn giản để tạo bảng và kết xuất dữ liệu từ bảng tạm thời của mình.

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

2
này có xung quanh sàn gỗ đọc lỗi tôi đã nhận được khi sử dụng write.saveAsTable trong spark 2.0
ski_squaw

2
Có, tuy nhiên, chúng ta có thể sử dụng phân vùng theo khung dữ liệu trước khi tạo bảng tạm. @chhantyal
Vinay Kumar

1
Làm thế nào bạn có thể trộn và kết hợp temporarybàn với hivebảng? Khi thực hiện show tablesnó chỉ bao gồm các hivebảng cho spark 2.3.0cài đặt của tôi
StephenBoesch

1
bảng tạm thời này sẽ được lưu vào ngữ cảnh tổ của bạn và không thuộc về các bảng tổ ong theo bất kỳ cách nào.
Vinay Kumar

1
xin chào @VinayKumar tại sao bạn lại nói "Nếu bạn đang sử dụng saveAsTable (nó giống như duy trì khung dữ liệu của bạn), bạn phải đảm bảo rằng bạn có đủ bộ nhớ được cấp cho ứng dụng spark". bạn có thể giải thích điểm này?
enneppi,

27

Sử dụng DataFrameWriter.saveAsTable. ( df.write.saveAsTable(...)) Xem Hướng dẫn Spark SQL và DataFrame .


4
saveAsTable không tạo bảng tương thích với Hive. Giải pháp tốt nhất mà tôi tìm thấy là của Vinay Kumar.
RChat

@Jacek: Tôi đã tự thêm ghi chú này, vì tôi nghĩ câu trả lời của mình là sai. Tôi sẽ xóa nó, ngoại trừ việc nó được chấp nhận. Bạn có nghĩ rằng ghi chú là sai?
Daniel Darabos 27/12/16

Đúng. Ghi chú đã sai và đó là lý do tại sao tôi đã xóa nó. "Xin vui lòng sửa cho tôi nếu tôi sai" áp dụng ở đây :)
Jacek Laskowski

1
điều này df.write().saveAsTable(tableName) cũng sẽ ghi dữ liệu phát trực tuyến vào bảng?
user1870400

1
không bạn không thể lưu trực tuyến dữ liệu với saveAsTable nó không phải là ngay cả trong api
Brian

20

Tôi thấy df.write.saveAsTable(...)tài liệu Spark 2.0 không còn được dùng nữa. Nó đã hoạt động cho chúng tôi trên Amazon EMR. Chúng tôi hoàn toàn có thể đọc dữ liệu từ S3 vào khung dữ liệu, xử lý nó, tạo bảng từ kết quả và đọc nó bằng MicroStrategy. Câu trả lời của Vinays cũng đã hoạt động.


5
Ai đó đã gắn cờ câu trả lời này là chất lượng thấp do độ dài và nội dung. Thành thật mà nói, nó có lẽ sẽ tốt hơn như một bình luận. Tôi đoán nó đã được hai năm và một số người đã thấy nó hữu ích nên có thể tốt nếu để mọi thứ như vậy?
serakfalcon

Tôi đồng ý, bình luận sẽ là lựa chọn tốt hơn. Bài học kinh nghiệm :-)
Alex

15

bạn cần phải có / tạo một HiveContext

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

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

Sau đó trực tiếp lưu dataframe hoặc chọn các cột để lưu trữ dưới dạng bảng hive

df là khung dữ liệu

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

hoặc là

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

hoặc là

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

SaveModes là Nối / Bỏ qua / Ghi đè / ErrorIfExists

Tôi đã thêm vào đây định nghĩa cho HiveContext từ Tài liệu Spark,

Ngoài SQLContext cơ bản, bạn cũng có thể tạo HiveContext, cung cấp một tập hợp siêu chức năng được cung cấp bởi SQLContext cơ bản. Các tính năng bổ sung bao gồm khả năng viết truy vấn bằng trình phân tích cú pháp HiveQL hoàn chỉnh hơn, quyền truy cập vào các UDF của Hive và khả năng đọc dữ liệu từ các bảng Hive. Để sử dụng HiveContext, bạn không cần phải có thiết lập Hive hiện có và tất cả các nguồn dữ liệu có sẵn cho SQLContext vẫn có sẵn. HiveContext chỉ được đóng gói riêng biệt để tránh bao gồm tất cả các phụ thuộc của Hive trong bản dựng Spark mặc định.


trên phiên bản Spark 1.6.2, sử dụng "dbName.tableName" gây ra lỗi này:

org.apache.spark.sql.AnalysisException: Không cho phép chỉ định tên cơ sở dữ liệu hoặc các định tính khác cho các bảng tạm thời. Nếu tên bảng có dấu chấm (.), Vui lòng trích dẫn tên bảng bằng dấu gạch ngược (). '


Là lệnh thứ hai: 'df.select (df.col ("col1"), df.col ("col2"), df.col ("col3")) .write (). Mode ("ghi đè"). SaveAsTable ("schemaName.tableName"); ' yêu cầu rằng các cột được chọn mà bạn định ghi đè đã tồn tại trong bảng? Vì vậy, bạn có bảng hiện có và bạn chỉ ghi đè các cột hiện có 1,2,3 bằng dữ liệu mới từ df của bạn trong spark? điều đó được giải thích đúng không?
dieHellste

3
df.write().mode...cần phải được thay đổi đểdf.write.mode...
sử dụng 923.227

8

Lưu vào Hive chỉ là một vấn đề của việc sử dụng write()phương pháp của SQLContext của bạn:

df.write.saveAsTable(tableName)

Xem https://spark.apache.org/docs/2.1.0/api/java/org/apache/spark/sql/DataFrameWriter.html#saveAsTable(java.lang.String)

Từ Spark 2.2: sử dụng DataSet thay vì DataFrame.


Dường như tôi gặp lỗi khi cho biết Công việc đã bị hủy bỏ. Tôi đã thử mã sau đây pyspark_df.write.mode ("ghi đè"). SaveAsTable ("InjuryTab2")
Sade

Chào! tại sao là cái này? From Spark 2.2: use DataSet instead DataFrame.
onofricamila

3

Xin lỗi vì viết bài muộn nhưng tôi không thấy câu trả lời nào được chấp nhận.

df.write().saveAsTablesẽ ném AnalysisExceptionvà không tương thích với bảng HIVE.

Lưu trữ DF như df.write().format("hive")nên làm thủ thuật!

Tuy nhiên, nếu điều đó không hiệu quả, thì hãy xem xét các nhận xét và câu trả lời trước đó, đây là giải pháp tốt nhất theo ý kiến ​​của tôi (Mặc dù vậy, hãy mở cho các đề xuất).

Cách tốt nhất là tạo bảng HIVE một cách rõ ràng (bao gồm cả bảng PARTITIONED),

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

lưu DF dưới dạng bảng tạm thời,

df.createOrReplaceTempView("$tempTableName")

và chèn vào bảng HIVE PARTITIONED:

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)

Nói cách khác CỘT CUỐI CÙNG trong DF sẽ là CỘT ĐỐI TÁC vì vậy hãy tạo bảng HIVE cho phù hợp!

Hãy bình luận nếu nó hoạt động! hay không.


- NGÀY--

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

Đây là phiên bản PySpark để tạo bảng Hive từ tệp gỗ. Bạn có thể đã tạo tệp Parquet bằng cách sử dụng lược đồ được suy luận và bây giờ muốn chuyển định nghĩa sang Hive di căn. Bạn cũng có thể đẩy định nghĩa vào hệ thống như AWS Glue hoặc AWS Athena và không chỉ cho Hive di căn. Ở đây tôi đang sử dụng spark.sql để đẩy / tạo bảng vĩnh viễn.

   # 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

Đối với các bảng bên ngoài Hive, tôi sử dụng hàm này trong 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

Trong trường hợp của tôi, điều này hoạt động tốt:

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

Làm xong!!

Bạn có thể đọc Dữ liệu, cho phép bạn cung cấp là "Nhân viên"

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

Để biết thêm chi tiết, hãy sử dụng URL này: https://docs.cloudera.com/HDPDocuments/HDP3/HDP-3.1.5/integrating-hive/content/hive-read-write-operations.html


0

Nếu bạn muốn tạo một bảng hive (không tồn tại) từ khung dữ liệu (một số lần không tạo được bằng khung dữ liệuDataFrameWriter.saveAsTable ). StructType.toDDLsẽ giúp liệt kê các cột dưới dạng một chuỗi.

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_tablesẽ được tạo trong không gian mặc định vì chúng tôi không cung cấp bất kỳ cơ sở dữ liệu nào tại spark.sql(). stg.hive_tablecó thể được sử dụng để tạo hive_tabletrong stgcơ sở dữ liệu.


Ví dụ chi tiết được tìm thấy tại đây: stackoverflow.com/a/56833395/1592191
mrsrinivas

0

Bạn có thể sử dụng thư viện spark-llap của Hortonworks như thế này

import com.hortonworks.hwc.HiveWarehouseSession

df.write
  .format("com.hortonworks.spark.sql.hive.llap.HiveWarehouseConnector")
  .mode("append")
  .option("table", "myDatabase.myTable")
  .save()
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.