È possibile salvare DataFrame
in Spark direttamente su Hive?
Ho provato a convertire DataFrame
in Rdd
e quindi salvare come file di testo e quindi caricare in hive. Ma mi chiedo se posso salvare direttamente dataframe
in hive
Risposte:
È possibile creare una tabella temporanea in memoria e archiviarla nella tabella hive utilizzando sqlContext.
Diciamo che il tuo data frame è myDf. Puoi creare una tabella temporanea utilizzando,
myDf.createOrReplaceTempView("mytempTable")
Quindi puoi utilizzare una semplice istruzione hive per creare una tabella ed eseguire il dump dei dati dalla tua tabella temporanea.
sqlContext.sql("create table mytable as select * from mytempTable");
temporary
tavolo con il hive
tavolo? Quando lo faccio show tables
include solo le hive
tabelle per la mia spark 2.3.0
installazione
Usa DataFrameWriter.saveAsTable
. ( df.write.saveAsTable(...)
) Vedere Spark SQL e Guida DataFrame .
df.write().saveAsTable(tableName)
scriverà anche i dati di streaming nella tabella?
Non vedo df.write.saveAsTable(...)
deprecato nella documentazione di Spark 2.0. Ha funzionato per noi su Amazon EMR. Siamo stati perfettamente in grado di leggere i dati da S3 in un dataframe, elaborarli, creare una tabella dal risultato e leggerla con MicroStrategy. Anche la risposta di Vinays ha funzionato.
devi avere / creare un HiveContext
import org.apache.spark.sql.hive.HiveContext;
HiveContext sqlContext = new org.apache.spark.sql.hive.HiveContext(sc.sc());
Quindi salva direttamente il dataframe o seleziona le colonne da memorizzare come tabella hive
df è dataframe
df.write().mode("overwrite").saveAsTable("schemaName.tableName");
o
df.select(df.col("col1"),df.col("col2"), df.col("col3")) .write().mode("overwrite").saveAsTable("schemaName.tableName");
o
df.write().mode(SaveMode.Overwrite).saveAsTable("dbName.tableName");
SaveModes sono Aggiungi / Ignora / Sovrascrivi / ErrorIfExists
Ho aggiunto qui la definizione per HiveContext dalla documentazione di Spark,
Oltre a SQLContext di base, puoi anche creare un HiveContext, che fornisce un superset delle funzionalità fornite da SQLContext di base. Altre funzionalità includono la possibilità di scrivere query utilizzando il parser HiveQL più completo, l'accesso alle UDF Hive e la capacità di leggere i dati dalle tabelle Hive. Per usare un HiveContext, non è necessario disporre di una configurazione Hive esistente e tutte le origini dati disponibili per un SQLContext sono ancora disponibili. HiveContext viene pacchettizzato solo separatamente per evitare di includere tutte le dipendenze di Hive nella build Spark predefinita.
su Spark versione 1.6.2, l'utilizzo di "dbName.tableName" restituisce questo errore:
org.apache.spark.sql.AnalysisException: non è consentito specificare il nome del database o altri qualificatori per le tabelle temporanee. Se il nome della tabella contiene punti (.), Si prega di citare il nome della tabella con i backtick ()
df.write().mode...
deve essere modificato indf.write.mode...
Salvare in Hive è solo questione di utilizzare il write()
metodo del tuo SQLContext:
df.write.saveAsTable(tableName)
Da Spark 2.2: usa DataSet invece DataFrame.
From Spark 2.2: use DataSet instead DataFrame.
Scusa se scrivo in ritardo al post ma non vedo risposta accettata.
df.write().saveAsTable
lancerà AnalysisException
e non è compatibile con la tabella HIVE.
Memorizzare DF come df.write().format("hive")
dovrebbe fare il trucco!
Tuttavia, se ciò non funziona, quindi, seguendo i commenti e le risposte precedenti, questa è la soluzione migliore secondo me (aperta ai suggerimenti però).
L'approccio migliore è creare esplicitamente la tabella HIVE (inclusa la tabella PARTITIONED),
def createHiveTable: Unit ={
spark.sql("CREATE TABLE $hive_table_name($fields) " +
"PARTITIONED BY ($partition_column String) STORED AS $StorageType")
}
salva DF come tabella temporanea,
df.createOrReplaceTempView("$tempTableName")
e inserire nella tabella PARTITIONED HIVE:
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)
Ovviamente l' ULTIMA COLONNA in DF sarà la COLONNA DI PARTIZIONE, quindi crea la tabella HIVE di conseguenza!
Si prega di commentare se funziona! o no.
--AGGIORNARE--
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
Ecco la versione di PySpark per creare un tavolo Hive da file parquet. Potresti aver generato file Parquet utilizzando uno schema dedotto e ora desideri inviare la definizione al metastore Hive. Puoi anche inviare la definizione al sistema come AWS Glue o AWS Athena e non solo al metastore Hive. Qui sto usando spark.sql per inviare / creare una tabella permanente.
# 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);
Per le tabelle esterne Hive utilizzo questa funzione in 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)
Nel mio caso funziona bene:
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()
Fatto!!
Puoi leggere i dati, lasciarti dare come "dipendente"
hive.executeQuery("select * from Employee").show()
Per maggiori dettagli usa questo URL: https://docs.cloudera.com/HDPDocuments/HDP3/HDP-3.1.5/integrating-hive/content/hive-read-write-operations.html
Potresti usare la libreria Spark-llap di Hortonworks in questo modo
import com.hortonworks.hwc.HiveWarehouseSession
df.write
.format("com.hortonworks.spark.sql.hive.llap.HiveWarehouseConnector")
.mode("append")
.option("table", "myDatabase.myTable")
.save()
Se vuoi creare una tabella hive (che non esiste) da un dataframe (a volte non riesce a creare con
DataFrameWriter.saveAsTable
).StructType.toDDL
aiuterà a elencare le colonne come una stringa.
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
verrà creato nello spazio predefinito poiché non abbiamo fornito alcun database in spark.sql()
. stg.hive_table
può essere utilizzato per creare hive_table
nel stg
database.