使用sparksql訪問(wèn)幾個(gè)hive表join的情況時(shí)結(jié)果為空,且這個(gè)sql在hive里執(zhí)行是成功的。
val sparkSession = SparkSession
.builder()
.config("jars","lib/*")
.appName("Spark Hive Example")
.enableHiveSupport()
.getOrCreate()
sparkSession.sql("select t1.c2,count(*) from t1 join t2 on (t1.c1=t2.c1) group by t1.c2").collect().map(r => mergeToOracle(r))
查看了t1,t2表的結(jié)構(gòu)
- t1是json格式,MR任務(wù)生成
- t2是parquet格式,sqoop導(dǎo)出
單獨(dú)查詢兩個(gè)表的結(jié)果
sparkSession.sql("select * from t1 limit 10").collect().map(r => println(r)) //正常顯示
sparkSession.sql("select * from t2 limit 10").collect().map(r => println(r)) //有結(jié)果,全部為null
因此可以判斷是讀parquet的結(jié)果出錯(cuò),因此導(dǎo)致兩個(gè)表join也沒(méi)有結(jié)果。如果直接按文件讀取parquet文件,使用臨時(shí)表查詢呢,結(jié)果正常顯示,且與其他表join也是正常。
sparkSession.read.parquet("/path of the hive table/").createOrReplaceTempView("temp_a")
val rs = sparkSession.sql("select * from temp_a")
rs.printSchema()
rs.show()
線上環(huán)境剛好還有另外一套sparksql運(yùn)行的beta環(huán)境,將sql拿去執(zhí)行是沒(méi)有問(wèn)題的,因此比較了當(dāng)前執(zhí)行環(huán)境和該beta環(huán)境的配制,發(fā)現(xiàn)其中有一個(gè)區(qū)別是spark.sql.hive.convertMetastoreParquet配制為false。
sparkSession.sqlContext.setConf("spark.sql.hive.convertMetastoreParquet","false")
加上這句之后數(shù)據(jù)正常了,這個(gè)配制有什么用,看字面也能理解了。
spark.sql.hive.convertMetastoreParquet default is true.When set to false, Spark
SQL will use the Hive SerDe for parquet tables instead of the built in support.
當(dāng)向Hive metastore中讀寫(xiě)Parquet表時(shí),Spark SQL將使用Spark SQL自帶的Parquet SerDe(SerDe:Serialize/Deserilize的簡(jiǎn)稱,目的是用于序列化和反序列化),而不是用Hive的SerDe,Spark SQL自帶的SerDe擁有更好的性能。這個(gè)優(yōu)化的配置參數(shù)為spark.sql.hive.convertMetastoreParquet,默認(rèn)值為開(kāi)啟。