Як зберегти DataFrame безпосередньо у Hive?


85

Чи можна заощадити DataFrameна іскрі безпосередньо у вулику?

Я спробував з перетворенням DataFrameв , Rddа потім зберегти у вигляді текстового файлу , а потім завантажуються в вулик. Але мені цікаво, чи можу я безпосередньо заощадити dataframeу вулику

Відповіді:


116

Ви можете створити тимчасову таблицю в пам'яті та зберегти їх у таблиці вуликів за допомогою sqlContext.

Скажімо, ваш фрейм даних - myDf. Ви можете створити одну тимчасову таблицю, використовуючи,

myDf.createOrReplaceTempView("mytempTable") 

Тоді ви можете використовувати простий оператор вулика для створення таблиці та скидання даних із вашої тимчасової таблиці.

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

2
це обійшло помилки читання паркету, які я отримував при використанні write.saveAsTable в іскрі 2.0
ski_squaw

2
Так, однак ми можемо використовувати розділ by на фреймі даних перед створенням тимчасової таблиці. @chhantyal
Vinay Kumar

1
Як ви змогли змішати та зіставити temporaryстіл із hiveтаблицею? При цьому show tablesвін включає лише hiveтаблиці для моєї spark 2.3.0інсталяції
StephenBoesch

1
ця тимчасова таблиця буде збережена у вашому контексті вуликів і жодним чином не належить до таблиць вуликів.
Vinay Kumar

1
привіт @VinayKumar, чому ти кажеш: "Якщо ви використовуєте saveAsTable (це більше схоже на збереження вашого кадру даних), ви повинні переконатися, що у вас достатньо пам'яті, виділеної для вашого іскрового додатка". Ви могли б пояснити цей момент?
enneppi

27

Використовуйте DataFrameWriter.saveAsTable. ( df.write.saveAsTable(...)) Див . Посібник Spark SQL та DataFrame .


4
saveAsTable не створює таблиць, сумісних з Hive. Найкраще рішення, яке я знайшов, - Віней Кумар.
RChat

@Jacek: Я сам додав цю нотатку, оскільки вважаю, що моя відповідь неправильна. Я б видалив його, за винятком того, що він прийнятий. Ви вважаєте, що примітка неправильна?
Даніель Дарабос,

Так. Нотатка була неправильною, і тому я її видалив. Тут застосовується "Будь ласка, виправте мене, якщо я помиляюся" :)
Яцек Ласковський

1
це df.write().saveAsTable(tableName) також запише потокові дані в таблицю?
user1870400

1
ні, ви не можете зберегти потокові дані за допомогою saveAsTable, це навіть не в api
Брайан

20

Я не бачу df.write.saveAsTable(...)застарілих у документації Spark 2.0. Це працювало для нас на Amazon EMR. Ми чудово змогли зчитувати дані з S3 у фрейм даних, обробляти їх, створювати таблицю з результату та читати за допомогою MicroStrategy. Відповідь Vinays також спрацювала.


5
Хтось позначив цю відповідь як неякісну через довжину та зміст. Чесно кажучи, це, мабуть, було б краще як коментар. Я думаю, це триває вже два роки, і деякі люди вважають це корисним, тому може бути добре залишити все як є?
serakfalcon

Я згоден, найкращим вибором був би коментар. Урок засвоєний :-)
Алекс

15

вам потрібно мати / створити HiveContext

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

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

Потім безпосередньо збережіть фрейм даних або виберіть стовпці, які потрібно зберегти як таблицю вуликів

df - кадр даних

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

або

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

або

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

Режими збереження - це Додавання / Ігнорувати / Перезаписати / ErrorIfExists

Я додав сюди визначення HiveContext із документації Spark,

На додаток до базового SQLContext, ви також можете створити HiveContext, який надає набір функціональних можливостей, що надаються базовим SQLContext. Додаткові функції включають можливість писати запити за допомогою більш повного аналізатора HiveQL, доступ до UDF Hive та можливість читати дані з таблиць Hive. Щоб використовувати HiveContext, вам не потрібно мати існуючу установку Hive, і всі джерела даних, доступні для SQLContext, як і раніше доступні. HiveContext упаковується лише окремо, щоб уникнути включення всіх залежностей Hive у збірку Spark за замовчуванням.


у Spark версії 1.6.2 використання "dbName.tableName" видає таку помилку:

org.apache.spark.sql.AnalysisException: Вказівки імені бази даних або інших кваліфікаторів не дозволяються для тимчасових таблиць. Якщо в назві таблиці є крапки (.), Процитуйте назву таблиці зворотними позначками (). `


Є другою командою: 'df.select (df.col ("col1"), df.col ("col2"), df.col ("col3")) .write (). Mode ("overwrite"). SaveAsTable ("schemaName.tableName"); ' вимагає, щоб вибрані стовпці, які ви збираєтеся перезаписати, вже існували в таблиці? Отже, у вас є існуюча таблиця, і ви лише перезаписуєте наявні стовпці 1,2,3 новими даними з вашого df в spark? це трактується правильно?
dieHellste

3
df.write().mode...потрібно змінити наdf.write.mode...
користувач 923227

8

Збереження в Hive - це лише питання використання write()методу вашого SQLContext:

df.write.saveAsTable(tableName)

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

З Spark 2.2: використовуйте DataSet замість DataFrame.


Здається, у мене помилка, яка стверджує, що робота перервана. Я спробував наступний код pyspark_df.write.mode ("перезаписати"). SaveAsTable ("InjuryTab2")
Сад

Привіт! чому це? From Spark 2.2: use DataSet instead DataFrame.
onofricamila

3

Вибачте, що пізно написав пост, але я не бачу прийнятої відповіді

df.write().saveAsTableкине AnalysisExceptionі не сумісний з таблицею HIVE.

Зберігання DF як df.write().format("hive")слід робити!

Однак, якщо це не спрацьовує, тоді, маючи на увазі попередні коментарі та відповіді, це найкраще рішення, на мій погляд (хоча відкрито для пропозицій).

Найкращий підхід - це явне створення таблиці HIVE (включаючи таблицю PARTITIONED),

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

зберегти DF як тимчасову таблицю,

df.createOrReplaceTempView("$tempTableName")

та вставте до таблиці РОЗДІЛЕНИХ УЛИЦ:

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)

Offcourse останній рядок в DF буде в розподільному стовпчики таким чином , створити Hive таблиці відповідно!

Будь ласка, коментуйте, якщо це працює! чи ні.


- UPDATE--

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

Ось версія PySpark для створення таблиці Hive з паркетного файлу. Можливо, ви створили файли паркету, використовуючи виведену схему, і тепер хочете передати визначення до метамагазину Hive. Ви також можете надіслати визначення до системи, як AWS Glue або AWS Athena, а не лише до метамагазину Hive. Тут я використовую spark.sql для натискання / створення постійної таблиці.

   # 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 я використовую цю функцію в 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

У моєму випадку це чудово працює:

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

Готово !!

Ви можете прочитати Дані, дозволити вам надати як "Працівник"

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

Для більш детальної інформації використовуйте цю URL-адресу: https://docs.cloudera.com/HDPDocuments/HDP3/HDP-3.1.5/integrating-hive/content/hive-read-write-operations.html


0

Якщо ви хочете створити таблицю вуликів (яка не існує) з фрейму даних (іноді це не вдається створити за допомогою DataFrameWriter.saveAsTable). StructType.toDDLwill допомагає перерахувати стовпці як рядок.

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_tableбуде створено у просторі за замовчуванням, оскільки ми не надали жодної бази даних на spark.sql(). stg.hive_tableможе використовуватися для створення hive_tableв stgбазі даних.


Докладний приклад тут: stackoverflow.com/a/56833395/1592191
mrsrinivas

0

Ви можете скористатися бібліотекою Hortonworks spark-llap, як це

import com.hortonworks.hwc.HiveWarehouseSession

df.write
  .format("com.hortonworks.spark.sql.hive.llap.HiveWarehouseConnector")
  .mode("append")
  .option("table", "myDatabase.myTable")
  .save()
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.