Sparkデータフレームのスキーマを使用してHiveテーブルを作成したいのですが、どうすればよいですか?
固定列の場合、次を使用できます。
val CreateTable_query = "Create Table my table(a string, b string, c double)"
sparksession.sql(CreateTable_query)
しかし、データフレームに多くの列があるので、そのようなクエリを自動的に生成する方法はありますか?
Spark 2.1.0以降でmy_DFがデータフレームである場合、
//get the schema split as string with comma-separated field-datatype pairs
StructType my_schema = my_DF.schema();
String columns = Arrays.stream(my_schema.fields())
.map(field -> field.name()+" "+field.dataType().typeName())
.collect(Collectors.joining(","));
//drop the table if already created
spark.sql("drop table if exists my_table");
//create the table using the dataframe schema
spark.sql("create table my_table(" + columns + ")
row format delimited fields terminated by '|' location '/my/hdfs/location'");
//write the dataframe data to the hdfs location for the created Hive table
my_DF.write()
.format("com.databricks.spark.csv")
.option("delimiter","|")
.mode("overwrite")
.save("/my/hdfs/location");
一時テーブルを使用する他の方法
my_DF.createOrReplaceTempView("my_temp_table");
spark.sql("drop table if exists my_table");
spark.sql("create table my_table as select * from my_temp_table");
質問のとおり、データフレームのスキーマを使用してHiveでテーブルを作成するようです。しかし、あなたが言っているように、あなたはそのデータフレームに多くの列があるので、2つのオプションがあります
次のコードを検討してください。
package Hive.example
import org.Apache.spark.SparkConf
import org.Apache.spark.SparkContext
import org.Apache.spark.sql.SQLContext
import org.Apache.spark.sql.Row
import org.Apache.spark.sql.SparkSession
object checkDFSchema extends App {
val cc = new SparkConf;
val sc = new SparkContext(cc)
val sparkSession = SparkSession.builder().enableHiveSupport().getOrCreate()
//First option for creating Hive table through dataframe
val DF = sparkSession.sql("select * from salary")
DF.createOrReplaceTempView("tempTable")
sparkSession.sql("Create table yourtable as select * form tempTable")
//Second option for creating Hive table from schema
val oldDFF = sparkSession.sql("select * from salary")
//Generate the schema out of dataframe
val schema = oldDFF.schema
//Generate RDD of you data
val rowRDD = sc.parallelize(Seq(Row(100, "a", 123)))
//Creating new DF from data and schema
val newDFwithSchema = sparkSession.createDataFrame(rowRDD, schema)
newDFwithSchema.createOrReplaceTempView("tempTable")
sparkSession.sql("create table FinalTable AS select * from tempTable")
}
spark 2.4以降では、関数dataframe.schema.toDDLを使用して列名と型を取得できます(ネストされた構造体の場合でも)
別の方法は、StructType..sql、simpleString、TreeStringなどで使用可能なメソッドを使用することです。
次に例を示します-(Till Spark 2.3)
// Sample Test Table to create Dataframe from
spark.sql(""" drop database Hive_test cascade""")
spark.sql(""" create database Hive_test""")
spark.sql("use Hive_test")
spark.sql("""CREATE TABLE Hive_test.department(
department_id int ,
department_name string
)
""")
spark.sql("""
INSERT INTO Hive_test.department values ("101","Oncology")
""")
spark.sql("SELECT * FROM Hive_test.department").show()
// Create DDL from Spark Dataframe Schema
val sqlrgx = """(struct<)|(>)|(:)""".r
val sqlString = sqlrgx.replaceAllIn(spark.table("Hive_test.department").schema.simpleString, " ")
spark.sql(s"create table Hive_test.department2( $sqlString )")
Spark 2.4以降では、StructTypeでfromDDLおよびtoDDLメソッドを使用できます-
val fddl = """
department_id int ,
department_name string,
business_unit string
"""
// fromDDL defined in DataType
//val schema3: DataType = org.Apache.spark.sql.types.DataType.fromDDL(fddl)
val schema3: StructType = org.Apache.spark.sql.types.StructType.fromDDL(fddl)
//toDDL defined in StructType
// Create DDL String from StructType
val tddl = schema3.toDDL
spark.sql(s"drop table if exists Hive_test.department2 purge")
spark.sql(s"""create table Hive_test.department2 ( $tddl )""")
spark.sql("""
INSERT INTO Hive_test.department2 values ("101","Oncology","MDACC Texas")
""")
spark.table("Hive_test.department2").show()
spark.sql(s"drop table Hive_test.department2")
以下は、寄木細工のファイルからHiveテーブルを作成するPySparkバージョンです。推論されたスキーマを使用してParquetファイルを生成し、定義をHiveメタストアにプッシュしたい場合があります。 Hiveメタストアだけでなく、AWS GlueやAWS Athenaなどのシステムに定義をプッシュすることもできます。ここでは、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);