DataFrame'i doğrudan Hive'a nasıl kaydedebilirim?


85

DataFrameKıvılcımdan doğrudan Hive'a kaydetmek mümkün müdür ?

Ben dönüştürerek ile çalıştık DataFrameetmek Rddve daha sonra bir metin dosyası olarak kaydetme ve sonra kovan yüklemede. Ama merak ediyorum doğrudan dataframekovana kurtarabilir miyim?

Yanıtlar:


118

Bellek içi geçici bir tablo oluşturabilir ve bunları sqlContext kullanarak kovan tablosunda saklayabilirsiniz.

Veri çerçevenizin myDf olduğunu varsayalım. Kullanarak bir geçici tablo oluşturabilirsiniz:

myDf.createOrReplaceTempView("mytempTable") 

Ardından, tablo oluşturmak ve verileri geçici tablonuzdan dökmek için basit bir kovan ifadesi kullanabilirsiniz.

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

2
bu, spark 2.0'da write.saveAsTable'ı kullanırken aldığım parke okuma hatalarını aştı
ski_squaw

2
Evet, ancak, temp tabloyu oluşturmadan önce veri çerçevesi üzerinde bölümleme kullanabiliriz. @chhantyal
Vinay Kumar

1
temporaryMasayı masayla nasıl karıştırıp eşleştirebildiniz hive? Bunu yaparken show tablesyalnızca enstalasyonum için hivetabloları içerirspark 2.3.0
StephenBoesch

1
bu geçici tablo kovan içeriğinize kaydedilecektir ve hiçbir şekilde kovan tablolarına ait değildir.
Vinay Kumar

1
merhaba @VinayKumar neden "saveAsTable kullanıyorsanız (daha çok veri çerçevenizi sürdürmek gibidir), spark uygulamanıza yeterince bellek ayırdığınızdan emin olmalısınız" diyorsunuz. bu noktayı açıklayabilir misin?
enneppi

28

Kullanım DataFrameWriter.saveAsTable . ( df.write.saveAsTable(...)) Bkz. Spark SQL ve DataFrame Kılavuzu .


4
saveAsTable, Hive uyumlu tablolar oluşturmaz. Bulduğum en iyi çözüm Vinay Kumar'a ait.
2016

@Jacek: Bu notu kendim ekledim çünkü cevabımın yanlış olduğunu düşünüyorum. Kabul edilmesi dışında onu silerim. Notun yanlış olduğunu mu düşünüyorsun?
Daniel Darabos

Evet. Not yanlıştı ve bu yüzden kaldırdım. "Yanlışsam lütfen beni düzeltin" burada geçerlidir :)
Jacek Laskowski

1
Bu, df.write().saveAsTable(tableName) akış verilerini de tabloya yazacak mı?
user1870400

1
hayır, akış verilerini saveAsTable ile kaydedemezsiniz, API'de bile değil
Brian

21

df.write.saveAsTable(...)Spark 2.0 belgelerinde kullanımdan kaldırıldığını görmüyorum . Bizim için Amazon EMR üzerinde çalıştı. S3'teki verileri bir veri çerçevesine mükemmel şekilde okuyabildik, işledik, sonuçtan bir tablo oluşturduk ve MicroStrategy ile okuyabildik. Vinays'ın cevabı da işe yaradı.


5
Uzunluk ve içerik nedeniyle birisi bu yanıtı düşük kaliteli olarak işaretledi. Dürüst olmak gerekirse, muhtemelen bir yorum olarak daha iyi olurdu. Sanırım iki yıldır devam ediyor ve bazı insanlar bunu faydalı buldu, bu yüzden her şeyi olduğu gibi bırakmak iyi olabilir mi?
serakfalcon

Katılıyorum, yorum yapmak daha iyi bir seçim olurdu. Ders öğrenildi :-)
Alex

15

bir HiveContext'e sahip olmanız / oluşturmanız gerekir

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

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

Ardından doğrudan veri çerçevesini kaydedin veya kovan tablosu olarak saklanacak sütunları seçin

df veri çerçevesidir

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

veya

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

veya

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

SaveMode'lar Ekle / Yoksay / Üzerine Yaz / HataIfExists

Buraya Spark Documentation'dan HiveContext tanımını ekledim,

Temel SQLContext'e ek olarak, temel SQLContext tarafından sağlanan işlevselliğin bir üst kümesini sağlayan bir HiveContext de oluşturabilirsiniz. Ek özellikler arasında daha eksiksiz HiveQL ayrıştırıcısını kullanarak sorgu yazma yeteneği, Hive UDF'lerine erişim ve Hive tablolarından veri okuma yeteneği bulunur. Bir HiveContext kullanmak için, mevcut bir Hive kurulumuna sahip olmanız gerekmez ve bir SQLContext için mevcut olan tüm veri kaynakları hala kullanılabilir durumdadır. HiveContext, varsayılan Spark yapısına Hive'ın tüm bağımlılıklarını dahil etmemek için yalnızca ayrı olarak paketlenir.


Spark sürüm 1.6.2'de "dbName.tableName" kullanıldığında şu hatayı verir:

org.apache.spark.sql.AnalysisException: Geçici tablolar için veritabanı adı veya diğer niteleyicilerin belirtilmesine izin verilmez. Tablo adında noktalar (.) Varsa, lütfen tablo adını ters işaretlerle () alın.


İkinci komut: 'df.select (df.col ("col1"), df.col ("col2"), df.col ("col3")) .write (). Mode ("overwrite"). SaveAsTable ("schemaName.tableName"); ' Üzerine yazmayı düşündüğünüz seçili sütunların tabloda zaten mevcut olmasını mı gerektiriyor? Yani mevcut tablonuz var ve kıvılcımdaki df'nizdeki yeni verilerle yalnızca mevcut sütun 1,2,3'ün üzerine mi yazıyorsunuz? bu doğru yorumlandı mı?
dieHellste

3
df.write().mode...şu şekilde değiştirilmelidirdf.write.mode...
kullanıcı 923227

8

write()Hive'a Kaydetmek, yalnızca SQLContext'inizin yöntemini kullanma meselesidir :

df.write.saveAsTable(tableName)

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

Spark 2.2'den: DataFrame yerine DataSet kullanın.


İşin iptal edildiğini belirten bir hatam var gibi görünüyor. Aşağıdaki kodu pyspark_df.write.mode ("overwrite") denedim. SaveAsTable ("InjuryTab2")
Sade

Selam! neden bu? From Spark 2.2: use DataSet instead DataFrame.
onofricamila

3

Gönderiye geç yazdığım için üzgünüm ama kabul edilmiş bir cevap göremiyorum.

df.write().saveAsTable atacak AnalysisException ve HIVE tablosu uyumlu değil.

DF'yi farklı saklama df.write().format("hive") hile yapmalıdır!

Ancak, bu işe yaramazsa, önceki yorum ve cevaplara göre, bence en iyi çözüm budur (Yine de önerilere açık).

En iyi yaklaşım, açıkça HIVE tablosu oluşturmaktır (BÖLÜNMELİ tablo dahil),

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

DF'yi geçici tablo olarak kaydedin,

df.createOrReplaceTempView("$tempTableName")

ve PARTITIONED HIVE tablosuna ekleyin:

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)

Tabii ki DF'deki SON SÜTUN , BÖLÜMLEME SÜTUNU olacaktır bu yüzden buna göre HIVE tablosu oluşturun!

Çalışırsa lütfen yorum yapın! ya da değil.


--GÜNCELLEME--

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

Parke dosyasından Hive tablosu oluşturmak için kullanılan PySpark versiyonu. Çıkarılan şema kullanarak Parquet dosyaları oluşturmuş olabilirsiniz ve şimdi tanımı Hive meta deposuna göndermek isteyebilirsiniz. Ayrıca tanımı yalnızca Hive metastore'a değil, AWS Glue veya AWS Athena gibi sisteme de aktarabilirsiniz. Burada kalıcı tabloyu itmek / oluşturmak için spark.sql kullanıyorum.

   # 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

Hive dış tabloları için PySpark'ta bu işlevi kullanıyorum:

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

Benim durumumda bu iyi çalışıyor:

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

Bitti !!

Verileri okuyabilirsiniz, "Çalışan" olarak verelim

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

Daha fazla ayrıntı için şu URL'yi kullanın: https://docs.cloudera.com/HDPDocuments/HDP3/HDP-3.1.5/integrating-hive/content/hive-read-write-operations.html


0

Hortonworks spark-llap kitaplığını bu şekilde kullanabilirsiniz

import com.hortonworks.hwc.HiveWarehouseSession

df.write
  .format("com.hortonworks.spark.sql.hive.llap.HiveWarehouseConnector")
  .mode("append")
  .option("table", "myDatabase.myTable")
  .save()

-1

Bir veri çerçevesinden (mevcut olmayan) bir kovan tablosu oluşturmak istiyorsanız (bazı zamanlar ile oluşturulamaz DataFrameWriter.saveAsTable). StructType.toDDLsütunların bir dizge olarak listelenmesine yardımcı olacaktır.

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_tableadresinde herhangi bir veritabanı sağlamadığımız için varsayılan alanda oluşturulacak spark.sql(). stg.hive_tableoluşturmak için kullanılabilir hive_tableiçinde stgveritabanı.


Burada ayrıntılı örnek bulunur: stackoverflow.com/a/56833395/1592191
mrsrinivas
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.