Hive
Hive簡介
Facebook為了解決海量日志數據的分析而開發了Hive,后來開源給了Apache軟件基金會。
官網定義:
The Apache Hive ? data warehouse software facilitates reading, writing, and managing large datasets residing in distributed storage using SQL.
Hive是一種用類SQL語句來協助讀寫、管理那些存儲在分布式存儲系統上大數據集的數據倉庫軟件。
Hive的幾個特點
Hive最大的特點是通過類SQL來分析大數據,而避免了寫MapReduce程序來分析數據,這樣使得分析數據更容易。
數據是存儲在HDFS上的,Hive本身并不提供數據的存儲功能
Hive是將數據映射成數據庫和一張張的表,庫和表的元數據信息一般存在關系型數據庫上(比如MySQL)。
數據存儲方面:它能夠存儲很大的數據集,并且對數據完整性、格式要求并不嚴格。
數據處理方面:因為Hive語句最終會生成MapReduce任務去計算,所以不適用于實時計算的場景,它適用于離線分析。
Hive架構
Hive的底層存儲
Hive的數據是存儲在HDFS上的。Hive中的庫和表可以看作是對HDFS上數據做的一個映射。所以Hive必須是運行在一個Hadoop集群上的。
Hive語句的執行過程
Hive中的執行器,是將最終要執行的MapReduce程序放到YARN上以一系列Job的方式去執行。
Hive的元數據存儲
Hive的元數據是一般是存儲在MySQL這種關系型數據庫上的,Hive和MySQL之間通過MetaStore服務交互。
Hive重要概念
外部表和內部表
內部表(managed table)
- 默認創建的是內部表(managed table),存儲位置在
hive.metastore.warehouse.dir
設置,默認位置是/user/hive/warehouse
。 - 導入數據的時候是將文件剪切(移動)到指定位置,即原有路徑下文件不再存在
- 刪除表的時候,數據和元數據都將被刪除
- 默認創建的就是內部表
create table xxx (xx xxx)
外部表(external table)
- 外部表文件可以在外部系統上,只要有訪問權限就可以
- 外部表導入文件時不移動文件,僅僅是添加一個metadata
- 刪除外部表時原數據不會被刪除
- 分辨外部表內部表可以使用
DESCRIBE FORMATTED table_name
命令查看 - 創建外部表命令添加一個external即可,即
create external table xxx (xxx)
- 外部表指向的數據發生變化的時候會自動更新,不用特殊處理
分區表和桶表
分區(partioned)
- 有些時候數據是有組織的,比方按日期/類型等分類,而查詢數據的時候也經常只關心部分數據,比方說我只想查2017年8月8號,此時可以創建分區,查詢具體某一天的數據時,不需要掃描全部目錄,所以會明顯優化性能
- 一個Hive表在HDFS上是有一個對應的目錄來存儲數據,普通表的數據直接存儲在這個目錄下,而分區表數據存儲時,是再劃分子目錄來存儲的
- 使用
partioned by (xxx)
來創建表的分區
分桶(clustered)
- 分桶是相對分區進行更細粒度的劃分。分桶將整個數據內容安裝某列屬性值得hash值進行區分,按照取模結果對數據分桶。如取模結果相同的數據記錄存放到一個文件。
- 桶表也是一種用于優化查詢而設計的表類型。創建通表時,指定桶的個數、分桶的依據字段,hive就可以自動將數據分桶存儲。查詢時只需要遍歷一個桶里的數據,或者遍歷部分桶,這樣就提高了查詢效率。
具體說明分桶
- clustered by (user_id) sorted by(leads_id) into 10 buckets
clustered by是指根據user_id的值進行哈希后模除分桶個數,根據得到的結果,確定這行數據分入哪個桶中,這樣的分法,可以確保相同user_id的數據放入同一個桶中。
sorted by 是指定桶中的數據以哪個字段進行排序,排序的好處是,在join操作時能獲得很高的效率。
into 10 buckets是指定一共分10個桶。
在HDFS上存儲時,一個桶存入一個文件中,這樣根據user_id進行查詢時,可以快速確定數據存在于哪個桶中,而只遍歷一個桶可以提供查詢效率。
Hive文件格式
hive文件存儲格式包括以下幾類:
- TEXTFILE
- SEQUENCEFILE
- RCFILE
- ORCFILE(0.11以后出現)
其中TEXTFILE為默認格式,建表時不指定默認為這個格式,導入數據時會直接把數據文件拷貝到hdfs上不進行處理;SEQUENCEFILE,RCFILE,ORCFILE格式的表不能直接從本地文件導入數據,數據要先導入到textfile格式的表中, 然后再從表中用insert導入SequenceFile,RCFile,ORCFile表中。
列式存儲和行式存儲
首先我們看一下一張表的存儲格式
行式存儲
列式存儲
列式存儲和行式存儲的比較
行式存儲
優點:
- 相關的數據是保存在一起,比較符合面向對象的思維,因為一行數據就是一條記錄
- 這種存儲格式比較方便進行INSERT/UPDATE操作
缺點:
- 如果查詢只涉及某幾個列,它會把整行數據都讀取出來,不能跳過不必要的列讀取。當然數據比較少,一般沒啥問題,如果數據量比較大就比較影響性能
- 由于每一行中,列的數據類型不一致,導致不容易獲得一個極高的壓縮比,也就是空間利用率不高
- 不是所有的列都適合作為索引
列式存儲
優點:
- 查詢時,只有涉及到的列才會被查詢,不會把所有列都查詢出來,即可以跳過不必要的列查詢
- 高效的壓縮率,不僅節省儲存空間也節省計算內存和CPU
- 任何列都可以作為索引
缺點:
- INSERT/UPDATE很麻煩或者不方便
- 不適合掃描小量的數據
TEXTFILE
默認格式,數據不做壓縮,磁盤開銷大,數據解析開銷大。
可結合Gzip、Bzip2使用(系統自動檢查,執行查詢時自動解壓),但使用這種方式,hive不會對數據進行切分,從而無法對數據進行并行操作。
SEQUENCEFILE
SequenceFile是Hadoop API提供的一種二進制文件支持,其具有使用方便、可分割、可壓縮的特點。
SequenceFile支持三種壓縮選擇:NONE,RECORD,BLOCK。Record壓縮率低,一般建議使用BLOCK壓縮。
RCFILE
RCFILE是一種行列存儲相結合的存儲方式。首先,其將數據按行分塊,保證同一個record在一個塊上,避免讀一個記錄需要讀取多個block。其次,塊數據列式存儲,有利于數據壓縮和快速的列存取。
- RCFile保證同一的數據位于同一節點,因此元組重構代價較低(需要將分散的數據重新組織,比如一列數據散落在不同集群,查詢的時候,需要將各個節點的數據重新組織;但是如果數據都在一個機器上,那就沒有必要重新組織)
- RCFile通過列進行數據壓縮,因為同一列都是相同的數據類型,所以壓縮比比較好
- RCFile可以跳過不必要的列讀取
從以上幾點也可以看出它是兼顧了行式和列式存儲的部分優點。
ORC File
ORCFile存儲格式,就是Optimized RC File的縮寫。意指優化的RCFile存儲格式。
ORC File 和 RC File比較
- 每一個任務只輸出單個文件,這樣可以減少NameNode的負載
- 支持各種復雜的數據類型,比如datetime,decimal,以及復雜的struct,List,map等
- 在文件中存儲了輕量級的索引數據
- 基于數據類型的塊模式壓縮:比如Integer類型使用RLE(RunLength Encoding)算法,而字符串使用字典編碼(DictionaryEncoding)
- 使用單獨的RecordReader并行讀相同的文件
- 無需掃描標記就能分割文件
- 綁定讀寫所需要的內存
- 元數據存儲使用PB,允許添加和刪除字段
Hive ROW FORMAT
Serde是 Serializer/Deserializer的簡寫。hive使用Serde進行行對象的序列與反序列化。
你可以創建表時使用用戶自定義的Serde或者native Serde,如果 ROW FORMAT沒有指定或者指定了 ROW FORMAT DELIMITED就會使用native Serde。
hive已經實現了許多自定義的Serde,之前我們在介紹stored時也涉及到:
- 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)
Hive寫入數據的方式
和我們熟悉的關系型數據庫不一樣,Hive現在還不支持在insert語句里面直接給出一組記錄的文字形式,也就是說,Hive并不支持INSERT INTO …. VALUES形式的語句(目前新版本早已支持,但是并不十分建議使用,性能和可用性方面難以滿足要求)。
從本地文件系統中導入數據到Hive表
load data local inpath 'xxx.txt' into table xxx;
從HDFS上導入數據到Hive表
load data inpath '/home/xxx/add.txt' into table xxx
alter table db.access_log add partition (dt='18-09-18') location 'hdfs://ns/hive/warehouse/access_log/dt=18-09-18';
從別的表中查詢出相應的數據并導入到Hive表中
insert overwrite table db.log_v2 partition(dt='18-09-26') select uid,model,key,value,time from db.log where dt='18-09-26';
在創建表的時候通過從別的表中查詢出相應的記錄并插入到所創建的表中
create table test4 as select id, name, tel from xxx;
歡迎關注 高廣超的簡書博客 與 收藏文章 !
歡迎關注 頭條號:互聯網技術棧 !
個人介紹:
高廣超:多年一線互聯網研發與架構設計經驗,擅長設計與落地高可用、高性能、可擴展的互聯網架構。目前從事大數據相關研發與架構工作。
本文首發在 高廣超的簡書博客 轉載請注明!