SparkSQL 初步應用(HiveContext使用),sparksqlhive
折騰了一天,終於解決了上節中result3的錯誤。至於為什麼會產生這個錯誤,這裡,先賣個關子,先看看這個問題是如何發現的:
首先,找到了這篇文章:http://apache-spark-user-list.1001560.n3.nabble.com/SparkSQL-select-syntax-td16299.html 裡面有這麼一段:
The issue is that you're using SQLContext instead of HiveContext. SQLContext implements a smaller subset of the SQL language and so you're getting a SQL parse error because it doesn't support the syntax you have. Look at how you'd write this in HiveQL, and then try doing that with HiveContext.
In fact, there are more problems than that. The sparkSQL will conserve (15+5=20) columns in the final table, if I remember well. Therefore, when you are doing join on two tables which have the same columns will cause doublecolumn error.
這裡提及到兩點:(1)使用HiveContext;(2)也就是導致這個錯誤的原因。
好吧,說到使用HiveContext,那咱就用HiveContext(尼瑪,這裡折騰了半天):
首先呢,看使用HiveContext都需要哪些要求,這裡參考了這篇文章:http://www.cnblogs.com/byrhuangqiang/p/4012087.html
文章中有這麼三個要求:
1、檢查$SPARK_HOME/lib目錄下是否有datanucleus-api-jdo-3.2.1.jar、datanucleus-rdbms-3.2.1.jar 、datanucleus-core-3.2.2.jar 這幾個jar包。
2、檢查$SPARK_HOME/conf目錄下是否有從$HIVE_HOME/conf目錄下拷貝過來的hive-site.xml。
3、提交程式的時候將資料庫驅動程式的jar包指定到DriverClassPath,如bin/spark-submit --driver-class-path *.jar。或者在spark-env.sh中設定SPARK_CLASSPATH。
那咱就按照要求配置,可是,配置完成之後報錯(互動模式):
Unable to instantiate org.apache.hadoop.hive.metastore.HiveMetaStoreClient
初步判斷,是hive串連來源資料庫這塊的問題,於是在hive-site.xml檔案中添加串連來源資料庫的參數:
<property>
<name>hive.metastore.uris</name>
<value>thrift://111.121.21.23:9083</value>
<description></description>
</property>
指定好參數之後,滿懷期待的執行了個查詢,尼瑪又報錯(這個錯誤糾結了好久):
ERROR ObjectStore: Version information not found in metastore.
這個錯誤說的是,在使用HiveContext時,需要訪問Hive的資料來源,擷取資料來源的版本資訊,如果擷取不到,此時就會拋出該異常。關於解決方案網上倒是挺多,需要添加參數到hive-site.xml檔案:
<property>
<name>hive.metastore.schema.verification</name>
<value>false</value>
<description></description>
</property>
添加完參數,重啟了Hive服務,執行Spark 的HiveContext,依舊報改錯。使用IDE將程式編譯打包後,放在伺服器上執行:
#!/bin/bash
cd /opt/huawei/Bigdata/DataSight_FM_BasePlatform_V100R001C00_Spark/spark/
./bin/spark-submit \
--class HiveContextTest \
--master local \
--files /opt/huawei/Bigdata/hive-0.13.1/hive-0.13.1/conf/hive-site.xml \
/home/wlb/spark.jar \
--archives datanucleus-api-jdo-3.2.6.jar,datanucleus-core-3.2.10.jar,datanucleus-rdbms-3.2.9.jar \
--classpath /opt/huawei/Bigdata/hive-0.13.1/hive-0.13.1/lib/*.jar
無奈,又報另一個錯(真是崩潰!):java.net.UnknownHostException: hacluster
這是hadoop的dfs.nameservices
嗯,不能解析主機名稱hacluster拋出的異常,那麼繼續,網上給的結果是:
需要把配置hdfs-site.xml複製到spark的conf目錄下,果然,複製完成後,程式打成的jar包終於能在伺服器上成功運行了。
但是回想起來,那麼這個錯誤:ERROR ObjectStore: Version information not found in metastore.
到底是由於什麼原因導致的?執行jar包和shell模式有什麼區別呢?
繼續,使用shell模式執行基於HiveContext的SQL,還是報這個錯,那麼,開啟spark的debug看看有什麼有價值的資訊,找個許久,沒有發現任何有價值的日誌。繼續在網上搜尋,網上的這個問題,都是WARN層級的,而我的是ERROR層級的。
到這裡,實在是沒有什麼思路了。哎,既然我的jar包能夠執行成功,那麼就看看使用jar包執行和該模式有什麼區別?
首先想到的是,為什麼hive-site.xml的參數:hive.metastore.schema.verification 沒有生效?我重啟服務了呀,是不是沒有引用到該參數?!
哎,那我就添加HIVE_HOME環境變數,執行了一下,還是沒生效,也就是說沒有引用到該參數。。。已經瀕臨崩潰,過了許久,突然想到,我執行的spark-shell命令來源於哪?那麼看一下:which spark-shell
好像發現了什麼,該spark-shell是來自spark用戶端程式的bin目錄(之前為了使用命令方便,設定和了環境變數---華為的產品),也就是說,我預設的環境變數是指向spark用戶端程式目錄的!!!
終於找到了問題的根本,於是,將hive-site.xml、hdfs-site.xml複製到用戶端程式的conf目錄下,重啟hive服務,一切OK!
過了一會,還有點不放心,到底是不是這個問題導致的呢?好吧,那麼就在其他節點上測試了一下,首先用戶端程式目錄中沒有該參數,執行失敗,添加後,hive.metastore.schema.verification是生效的!
大功告成!整個過程,spark的debug功能一直是開啟的,但是在日誌中沒有發現有價值的資訊。
對了,要想使用IDE調試Spark的HiveContext程式,需要在main目錄下添加resource目錄(類型為Resources),並且將hive-site.xml、hdfs-site.xml添加到該目錄中。
並且將三個驅動包引入:
datanucleus-api-jdo-3.2.6.jar,datanucleus-core-3.2.10.jar,datanucleus-rdbms-3.2.9.jar
差點忘了,我是為瞭解決上節中的result3問題,哈哈,這個問題其實是由於SparkSQL對SQL文法支援的問題。可以考慮使用其他方式(不在IN裡面嵌套子查詢),比如設定多個RDD或者左右串連等(有待測試)。