hive各版本主要特徵
Hive 各版本關鍵新特性(Key New Feature)介紹
官網下載頁面的介紹
hive基礎
命令列介面
hive提供的使用者介面包括:CLI、Client、WebUI幾種方式,我們平常主要使用CLI方式,未來叢集升級之後可能會有提供可視化的介面允許我們直接從WebUi訪問。
早期的hive版本主要使用HIVE CLI(old),之後發展為使用BeeLine CLI(new),目前SA已經切換為使用beeline。在CLI模式下,我們常用的命令包括: set
用於查看和設定hive的配置參數,例如控制reduce數量、控制壓縮格式等。 add jars
添加額外的jar包到hive運行環境,例如自訂了UDF/UDAF的jar包,可以通過這種方式添加 。
hive> ! ls;可以在hive裡邊直接運行shell命令 dfs
例如運行hive> dfs -ls /src/gamein/g4_sdc/;這樣就不用開額外的session去運行hadoop fs -ls Hive Sql
hive sql文法和我們使用的mysql文法基本類似,具體可以參考官網【DDL】和【DML】,支援的運算子,字串、數字、日期等方法,內建的UDF,UDAF,UDTF參考官方手冊【UDF-WIKI】。UDTF我們用的比較少,但需要的情況下會非常好用,例如Lateral View和Explode的配合使用可以展開資料【一個lateral view的例子】。除了使用UDF-WIKI查看hive的函數,也可以在命令列裡邊查看。 hive> show functions; --顯示所有函數
hive> describe function substr; --查看函數[substr]的用法
OK
substr(str, pos[, len]) - returns the substring of str that starts at pos and is of length len orsubstr(bin, pos[, len]) - returns the slice of byte array that starts at pos and is of length len
Time taken: 1.368 seconds, Fetched: 1 row(s)
這個功能不像mysql那樣強大,mysql下支援“?”文法,例如在mysql命令列下查看load data的使用文法 mysql> ? load data;
Hive Serde
我們使用hive Serde的頻率未來會越來越高。hive serde是指資料IO的序列化和還原序列化,主要作用是解析hdfs檔案,識別其中的格式。早期的一些hive-serde包已經廢棄,最新文檔參考【官方serde-wiki】,目前hive支援的內建serde如下,未來我們升級到hive1.0之後,下面這些就全部可以用了。 Avro (Hive 0.9.1 and later) ORC (Hive 0.11 and later) RegEx Thrift Parquet (Hive 0.13 and later) CSV (Hive 0.14 and later) JsonSerDe (Hive 0.12 and later inhcatalog-core)
有很多團隊直接用hive sql 直接進行資料處理,其核心就是自訂Serde,US那邊比我們用的多一些。我們使用hive-serde的最典型情境就是快速查詢、過濾出今天的hdfs日誌, 使用的是RegEx(Regex)來按日誌類型(登陸、退出、儲值等)進行某些統計(如人數、儲值額),這個效率會比直接使用hadoop fs -text快很多,具體使用方式參考另外一篇ETL內部的wiki《hdfs上的資料查詢方法》。
說到檔案格式解析,需要注意hive日誌的預設分隔符號的設定,預設情況如下: 欄位分隔符號:'\x01',匯出為普通文本之後,可以用cat -A 來查看,在linux shell下能看到分隔字元顯示成^A mapItem分隔字元:'\x02',即字典的KV項與項之間的分隔字元,(kv'\x02'kv) mapKv分隔字元:'\x03',即字典的KV內之間的分隔字元(k\x02v)
掌握這些有助於我們將hive資料匯入、匯出為普通文本的時候避免出錯。
Transform & UDF & UDAF transform
如 果想在hive中嵌入自訂的mapreduce指令碼,就可以使用transform這種模式來完成一些複雜的操作,也能完成UDF、UDAF的一些功 能。BI用的比較少,US的童鞋之前用的多一些。transform執行效率其實不高,但貴在可以用python快速的完成某個功能編寫,這比使用 JAVA編寫UDF/UDAF的擴充類、並打包發布來的快很多。下面是一個hive+python的例子。利用transform功能我們很容易完成諸 如,將資料群組合成數組、有序字典和其他一些複雜的日誌拆分功能。
【參考手冊-transform】 UDF & UDAF
自 定義函數UDF和自訂聚集合函式UDAF,會依賴一些jar包,並必須繼承相應的介面。相應的具體例子,大家可以在網上自行搜尋,編寫的過程和 MapReduce代碼非常相似。UDF和UDAF的執行效率比Transform快一些。我們在etl_hadoop_lib項目中有一些例子,比如 MaxRow方法介紹如下:MaxRow(compare_col,col1,col2,col3....) 根據指定的compare列進行比較,返回最大行,包含值compare-col,col1,col2...返回結構是struct,需要根據 struct結構取值。
Transform方式和UDF、UDAF的比較可以參照上圖右。 HIVE最佳化 理解HIVE
hive詳細的設計架構如下。
經過一定的發展,現在形成了如下的層次
最頂層是sql解析和執行計畫;中介層是計算架構,已經從最初的MapReduce發展為支援基於DAG的Tez和SPARK。最底層是資料的儲存,從最初的textfile/sequencefile擴充到更快更優的格式,如ORC File。
Hive on Mapreduce
在 hive主要使用MR做執行引擎,Tez是對MR執行過程的最佳化。所以,我們對hive的執行效率的最佳化,核心需要對Hive實際執行環境的 MapReduce過程進行最佳化。MapReduce的詳細過程見下圖(參考《hadoop權威指南》),記住這張圖,能幫我們很多忙,比如資料扭曲引起 的單個reduce太忙,表現就是reduce到98%、99%之後一直卡住,為了讓資料更均勻地分散,需要將key散列到更多的partition。理 解MapReduce的各個環節,也可以幫我們理解Hive發展的最佳化方向,例如tez將傳統reduce to localfile -> copy -> map ->reduce這些環節所見為 reduce -> reduce,另外考慮到hive要讀寫hdfs,更好的壓縮、解壓效率需要使用更優的檔案格式如ORC File等,而Spark則直接避免資料寫硬碟,而改用記憶體。
Hive JOIN
理解hive的集中join方式,能夠協助我們更好的理解大部分的資料關聯問題,有興趣的童鞋嘗試自己用MapReduce實現hive-join類似的功能。據說面試官們特別喜歡拿hive-join來考察對方對MR的理解。 reduce-side join ( common join)
注意執行順序,關聯相同的key可以減少一次MapReduce的執行過程。 map join
將其中一張小表全部載入記憶體。載入記憶體有資料大小的限制。偶爾這個是觸發報錯的原因。hive在某個版本之後實現了bloom filter,來擴充記憶體的限制。 bucket map join left-semi join
關於hive-join的具體過程可以參考【官方LanguageManual JoinOptimization】【join詳解】【Hive JOIN使用詳解】。順便談一下hive的排序,有sort by / order by /distribute by/ cluster by ,其中的差別參考【手冊-sortby】
hive-sql的最佳化可以參考這篇文章,講的還不錯,裡邊有原理和詳細的hive參數的設定【深入淺出資料倉儲中SQL效能最佳化之Hive篇】。hive核心的參數設定,上面幾篇文章都有,本文不再做具體的參數講解。
檔案格式與壓縮
hive 的資料是儲存在hdfs上,預設都是備份3份。採用不同的壓縮方法,對於磁碟的要求是差別非常大。另外,hive語句的執行效率與檔案格式的關係也非常 大。總的來說,如果壓縮的特別小,解壓效率就會差一些,最終需要在壓縮、解壓效率之間取得一個平衡。下面這個圖通過圓圈面積的大小形象地描述了不同檔案格 式如TextFile、SequenceFile、RCFILE、AVRO、PARQUET、ORCFile與不同壓縮演算法gz、snappy、 bzip2、Lzo組合情況下的直觀比例。
我 們肉眼能看的只有Text未壓縮的格式。但textfile壓縮之後,就不是splitable的,也就是在MapR的執行過程中只能當成一大塊,這樣會 極大的影響效率。從效能的角度講,以後的日誌格式會更多的選擇ORC(RCFile的改進) , Parquet (google傳說中3秒查詢1PB資料的Dremel的開源實現版)。有興趣的童鞋可以仔細的研究一下這兩種檔案儲存體。
我們目前的中間結果是用sequencefile儲存的,在MapReduce的指令碼裡邊選用的壓縮是gz(壓縮率高、解壓慢),hive預設是snappy。未來可能會做調整為ORC + tez引擎,以進一步提高hive的執行速度。
HIVE執行引擎的進化:Hive/Tez
Tez是Apache開源的支援DAG作業的計算架構,它直接源於MapReduce架構。中文介紹可以看董的部落格《Apache Tez:一個運行在YARN之上支援DAG作業的計算架構》。下面的這張圖以一條sql語句為例,描述了hive/mr與hive/tez的主要區別。
目前的hive版本已經支援tez引擎,只要下面的一條hive命令就可以完成engine的切換。
hive> set hive.execution.engine=tez;
另 外,hive其實也是支援spark引擎的。本文不對spark做額外的介紹,但hive-on-spark的效能並不是很理想,其效能不如直接使用 SPARK-SQL效率高。我們現在已經有部分sql已經改用SAPRK-SQL來執行了,碰到的SPARK-SQL的主要問題包括:1. 特別吃記憶體,需要對不同作業的記憶體參數分別配置;2. 對於資料量很大的情況,容易記憶體溢出,即便記憶體不溢出,執行效率也不是很理想,例如計算所有手遊的沉默使用者,計算慢的你會想哭。
我們現在的 hive任務的執行引擎已經預設是tez了,但還沒有結合ORCFile進行測試。對於小作業,可以直接用spark-sql,資料量特別大的作業,目前 更優的選擇是tez+orcFile的運行模式。那我們什麼時候需要改變呢,除非spark未來寄出更多的大招。下面是Hortnworks,tez的主 要開發最佳化者,對於hive/tez,hive/spark,spark-sql做過的一個效能測試比較的一個截圖片段,最終結論大概是spark是狠 牛,但hive-tez並不虛,看hive-tez如何變100X。Spark-Sql、Cloudera-impala、Hortnwork-tez都 說自己是最牛的,這個需要我們在實際環境中、根據機器和資料自行比較判定。
NEXT
hive的過去、現在、與未來都在下面這張圖了。遇到不熟悉的名詞,請自行google,即便是用的百度,也不要告訴SA,會被他們鄙視的。不好意思,寫的有點長,歪樓了。
也許用不了太長時間,hive真能進入sub-second的時代。也可能那個時候不叫hive,或者是spark-sql,或者是別的什麼。為了好好鼓勵大家使用hive,祭出最後一張大招圖。
其他 類似工具 impala
cloudera 開源的一個‘interactive’ SQL query engine,能查詢儲存在Hadoop的HDFS和HBase中的PB級大資料,可以基於yarn運行,部署起來還是比較方便的,之前組內有發布過相關 的研究資料。Cloudera的一篇官方部落格在2016年4月發布的資料測試說,impala執行sql的即時響應可以秒殺Spark-Sql、 hive-tez,見《New SQL Benchmarks: Apache Impala (incubating) Uniquely Delivers Analytic Database Performance》,不貼圖了,免得以後不想用hive。impala沒有使用hive+mapreduce的架構,而是受到Google的Dremel啟發,借鑒了MPP並行資料庫的思想。(果然,抄google沒錯)。 Drill
官網描述可以“Query any non-relational datastore”,國內好像不是很火了,驗證了一句話,什麼都可以,就是什麼都不可以。 Presto
an open source ‘interactive’ SQL query engine built by facebook。支援PB位元組的互動式資料查詢。不適用MapReduce架構。目前Airbnb 和 Dropbox、好像美團也在使用Presto。 shark -> Spark-Sql
shark估計要跪,屬於spark子項目,但漸被spark-sql取代。國內的Spark社區灰常火熱,大家都覺得這是未來,Spark-sql估計會使用的越來越多。 BigSql (ibm提供的一個分布式sql查詢引擎,不開源,資料也少,貌似大家就不用關心了) Apache Phoenix(也是一個sql引擎,主要用來查hbase的,好像不用在這說) HAWQ(EMC提供,不開源)
個人感覺重點關注一下spark-sql,impala就可以。
與其他資料庫的互動 與hbase的互動
我 們可以通過hive來操作hbase。包括讀取hbase資料,以及通過hive-sql更新hive表的方式來更新hbase,前提是先建立hive表 與hbase表的映射關係。通常有兩種方式:1. Hbase的一個列族映射為hive的一個Map,map裡邊包含所有的列資訊。2. 將Hbase每個列族的所有列,分別映射為hive表的一列。各有優劣,視實際情況而定。hive與hbase的整合方法參考《Hive-HBaseIntegration》。
另外,hive還能協助產生HFile,目前有一定的限制條件,比如只允許只有個ColumnFamily。產生HFile之後,採用Bulkload的方法,是目前大批量資料刷寫Hhase最快的方法。 與Mysql的互動
使 用最廣泛的工具是Sqoop,啟動的是一個MapReduce的過程。“Apache Sqoop(TM) is a tool designed for efficiently transferring bulk data between Apache Hadoop and structured datastores such as relational databases.sqoop”。sqoop不僅限於hive,其實也能用於hbase等。最新穩定版是1.4.6,詳細的參數解釋和使用方法參考官方 《指引文檔-sqoop》
我們平時遇到的坑主要在於對非textfile的hdfs檔案如sequencefile是否支援、對NULL資料的如何處理等。
說明
1. 全文的圖片都是抄的,之前收藏剪輯的,不記得來源了。大概資料來源: 《hadoop權威指南》《hadoop實戰》《hadoop技術內幕》 董西成的部落格 Hortnworks、Cloudera的部落格 Hadoop Summit上面的一些ppt google/百度的圖片
2. sa的hive入口命令解釋
hive --config /home/hadoop/hiveconf/metastore/sy_sdc/ \
--auxpath /home/hadoop/hbase/lib \ # 如果要在hive裡邊訪問hbase,需要添加hbase包,
-hiveconf hive.new.job.grouping.set.cardinality=32 \ #cube維度上限,如果有N個維度,就需要設定上限>2^N
-hiveconf hive.exec.scratchdir=/tmp/hive-${whoami} ##調度器帳號和個人帳號需要使用不同的臨時目錄
3. 匯出select結果
一般用insert overwrite local directory的方法,在python下使用os.popen()方法,還會讀取到額外的hive執行過程的資訊。