參考《Hive實戰》
ASF是一個支持多種軟件開發項目的組織
Hive不是數據庫,而是一個友好且爲我們熟悉的接口,可以查詢存儲在HDFS上的底層數據文件
SerDe:序列化、反序列化
HCatlog促進了各種Hadoop組件之間實現模式共享,HCatlog的作用包括:
- 爲多種工具提供一種通用模式環境
- 允許各種工具通過連接器連接,進而從Hive倉庫讀取數據和向其寫入數據
- 使用戶可以跨工具共享數據
- 爲Hadoop中的數據創建一種關係結構
- 抽象出數據存儲的方式和位置
- 使模式和存儲的更改對用戶不可見
HCatlog本質上是數據訪問工具與底層文件之間的抽象層
HiveServer1的限制:用戶併發性、LDAP安全性集成
HiveServer2 架構基於一個ThriftService和任意數量由驅動程序、編譯器和執行器組成的會話。MetaStore也是HiveServer2的一個重要組成部分
支持Kerberos、自定義身份驗證以及通過LDAP身份驗證
HiveServer2在Hive1.1引入(HIVE-2935),提供更好的併發性、安全性、遠程訪問
Tez:
- 避免了代價高昂的混洗過程,因此避免了磁盤IO。在Tez執行引擎的執行計劃中,約簡器的中間數據將直接傳遞給下一個簡約器
- 採用了高效的Map端連接
- 採用了基於代價的優化器,有助於生成更快的執行計劃
- Tez與ORC文件格式聯合使用,查詢引擎的執行速度比本機MR快100倍
Tez相關配置:
hive.prewarm.enabled = true //Hive創建Tez容器
hive.prewarm.numcontainers //調整Tez專用容器的數量
表的屬性(TBLPROPERTIES):
- last_modified_user:
- last_modified_time:
- immutable:爲true時,無法在插入新行
- orc.compress:
- skip.header.line.count:調過底層數據的標題行
用show create table 生成創建表語句
分區最佳實踐:
- 挑選一列作爲分區鍵,其唯一值的個數應在較低值到中間值之間
- 避免分區小於1GB(越大越好)
- 當分區數量較多時,調整HiveServer2 和 Hive MetaStore的內存
- 當使用多列作爲分區鍵時,對於每一個分區鍵列的組合都要創建一個子目錄的嵌套樹
- 當使用Hive流處理插入數據時,如果多個會話向相同分區插入數據,那麼會導致鎖閉
- 一旦分區表的模式發生改變,將無法在已有分區上修改數據
- 如果要將數據並行插入到多個分區,應該將hive.optimize.sort.dynamic.partition設置爲true
對於日期列進行高效分區:
select * from table A where datestamp in ('2015-01-01','2015-02-03','2016-01-01');
select * from table A where datestamp like '2015-%';
select * from table A where datestamp like '2015-02-%';
select * from table A where datestamp like '%-%-%5';
select * from table A where datestamp between '2015-01-01' AND '2015-03-01'
schema - on - read
添加分區:
alter table add partition;
alter table xxx partition(xx) rename to partition(yy);
分桶:
- Hive中的分桶是另一種將數據切分爲更小片段的方式
- 分區鍵是表中的一個虛擬列,然而在分桶中,每個桶都是一個保存實際數據的文件,這些數據基於一種散列算法進行分割,分桶並不會爲當前表添加一個虛擬列
create table xx(xxxxxx) clusted by (xxx) into xx buckets location 'xxx'
分桶的最佳實踐:
- 選擇唯一值的個數較多的桶鍵。這樣會減小出現傾斜的可能性
- 採用質數作爲桶的編號
- 如果桶鍵中的數據是傾斜的,爲傾斜的值單獨創建桶。可以通過列表分桶來實現
- 需要連接在一起的表,桶的數目必須相同,或者一個表的桶數是另一個表的桶數的因子
- 一個CPU只會對一個桶進行寫入操作,如果桶的數目很小,集羣的利用嚴重不足
- 一旦表創建好,桶的數目就不能改變了
- 桶文件大小至少是1GB
- 通過設置hive.enforce.bucketing = true 實現強制分桶
- 對於map端連接,分桶表要比非分桶表的速度更快
Parquet:Parquet文件是以二進制方式存儲的,是不可以直接讀取和修改的,Parquet文件是自解析的,文件中包括該文件的數據和元數據。在HDFS文件系統和Parquet文件中存在如下幾個概念:
- HDFS塊(Block):它是HDFS上的最小的副本單位,HDFS會把一個Block存儲在本地的一個文件並且維護分散在不同的機器上的多個副本,通常情況下一個Block的大小爲256M、512M等。
- HDFS文件(File):一個HDFS的文件,包括數據和元數據,數據分散存儲在多個Block中。
- 行組(Row Group):按照行將數據物理上劃分爲多個單元,每一個行組包含一定的行數,在一個HDFS文件中至少存儲一個行組,Parquet讀寫的時候會將整個行組緩存在內存中,所以如果每一個行組的大小是由內存大的小決定的。
- 列塊(Column Chunk):在一個行組中每一列保存在一個列塊中,行組中的所有列連續的存儲在這個行組文件中。不同的列塊可能使用不同的算法進行壓縮。
- 頁(Page):每一個列塊劃分爲多個頁,一個頁是最小的編碼的單位,在同一個列塊的不同頁可能使用不同的編碼方式
p243 圖
ORC:(Parquet不如ORC)
ORC文件格式用於減少要從磁盤讀取的數據量(基於列),可以被分割的文件格式,可以分割成多個可並行處理的塊。
數據按行組切分,一個行組包含若干行,每行中再按列存儲(256MB的數據帶)
create table xxx stored as orc tblproperties("orc.compress"="snappy") as select * from xxx
ORC文件:保存在文件系統上的普通二進制文件,一個ORC文件中可以包含多個stripe,每一個stripe包含多條記錄,這些記錄按照列進行獨立存儲,對應到Parquet中的row group的概念
ORC格式相關的配置:
- orc.compress
- orc.compress.size
- orc.stripe.size 每個帶的字節數
- orc.row.index.stride 索引記錄之間的行數
- orc.create.index 是否要創建行索引
- hive.exec.orc.default.block.size
- hive.exec.orc.default.stripe.size
文件級元數據:包括文件的描述信息PostScript、文件meta信息(包括整個文件的統計信息)、所有stripe的信息和文件schema信息
orc三個層級信息:
- 文件級別:記錄了文件中所有stripe的位置信息
- stripe級別:每個stripe所存儲數據的統計信息
- row group級別:每10000行構成一個行組
- stripe(行):一組行形成一個stripe,每次讀取文件是以行組爲單位的,一般爲HDFS的塊大小,保存了每一列的索引和數據
- stripe元數據:保存stripe的位置、每一個列的在該stripe的統計信息以及所有的stream類型和位置。
- row group:索引的最小單位,一個stripe中包含多個row group,默認爲10000個值組成。
- stream(列):一個stream表示文件中一段有效的數據,包括索引和數據兩類。索引stream保存每一個row group的位置和統計信息,數據stream包括多種類型的數據,具體需要哪幾種是由該列類型和編碼方式決定
orc劃分多個block塊,每個orc block橫向切分成多個stripes(一組行對應一個stripe),每個stripe內部以列stream爲單位存儲
p238 圖
數據查找過程:
- 列索引 -----> 找到文件
- 文件索引 ----> 找到stripe,並通過stripe索引找到stripe塊
- stripe中的行組索引 ----> 找到行組
ORC所有類型都接受NULL值
ORC能確保Hive在工作時事務的支持
參考:https://blog.csdn.net/yu616568/article/details/51868447
CBO:
Hive的more查詢執行引擎一次處理一行,因此在嵌套循環中需要有多層虛擬方法調用,從CPU的視角來看是非常低效的。
矢量化查詢執行是一種Hive特性,其目的是按照每批1024行讀取數據,並且一次性對整個記錄集合應用操作,進而消除那些效率低下的問題。必須使用ORC格式,CBO幫助生成一個最優執行計劃,在該計劃的執行過程中,從磁盤讀取和處理的數據量已經儘可能早地減少,使工作更加高效
set hive.vectorized.execution.enabled = true;
合併表文件:
對於RCFile 或 ORCFile 格式存儲的Hive表,可以做如下操作:alter table states concatenate
該命令會將多個數據問價合併成較大的文件
單次MapReduce實現連接:
select xxx from table_A join table_B
on (table_A.xxx = table_B.xxx)
join table_C
on (table_C.xxx = tableB.xxx)
Apache NiFi:
適用於各種類型的數據裝載和攝入場景,提供了對數據傳輸作業進行設計、控制、管理和監視的無縫體驗
Hive對JSON數據的處理
1.使用UDF處理
create table json_table(json string);
load data inpath 'xxxx' into table json_table;
select get_json_object(json_table.json,'$') from json_table;
2.使用SerDe處理json
create table json_serde_table(xxxxxx)row format serde 'org.openx.data.jsonserde.JsonSerDe' with SERDEPROPERTIES("mapping._id" = "id");
load data inpath 'xxx' into table json_serde_table;
select * from json_serde_table;
LLAP
對亞秒級查詢需求快速的查詢執行和降低整個生態系統內任務的設置成本
附 Hive源碼線程池:
- HiveServer有兩個線程池,客戶端Connection對應的是HiveServer2-Handler-Pool,在ThriftBinaryCLIService中創建,最大線程數由hive.server2.thrift.max.worker.threads控制
- 後臺處理的線程池是HiveServer2-Background-Pool,在SessionManager中創建,最大線程數如果是安全版本,由hive.server.session.control.maxconnections控制,非安全版本由hive.server2.async.exec.threads控制
insert into & insert overwrite 區別
- insert into:以追加的方式向hive表尾追加數據
- insert overwrite:直接重寫數據,先刪除hive表的數據,再執行寫入操作
multipleoutput:https://www.cnblogs.com/codeOfLife/p/5452902.html
Hive archive:https://blog.csdn.net/mhtian2015/article/details/79010293
Hive shims: https://cloud.tencent.com/info/c641933662422f98726ea6e6cff2b22d.html