首先談一下關於hive和hbase的區別的疑問(完全不是一個東西):
本質上來說hive和hbase沒什么關系,雖然都是表,查數據等,但是他們根本就不是一個層面的東西
hive就是一個rapduce的一個包裝,hive就是將編寫的sql轉換成mapreduce任務
而hbase是什么呢?可以理解為是hdfs的一個包裝,本質是數據存儲的,一個nosql數據庫,部署與hdfs之上的,目的是克服hdfs在隨機讀寫上的缺點
你非得問hive和hbase有什么區別,那就相當於問mapreduce和hdfs有什么區別,所有談他們的區別完全沒有任何的意義
引入Hive原因:
– 對存在HDFS上的文件或HBase中的表進行查詢時,是要手工寫一堆MapReduce代碼
– 對於統計任務,只能由動MapReduce的程序員才能搞定
Hive基於一個統一的查詢分析層,通過SQL語句的方式對HDFS上的數據進行查詢、統計和分析
由此可以看出來hive適合做數據查詢、統計和分析,使用SQL語句(但是,hive的sql並不是一個標准的sql,只是類似於一個標准的sql,但不等價於一個標准的sql)對HDFS進行查詢(mapreduce也是對HDFS進行查詢等工作,所以hive本身並不會存儲數據)
Hive到底是什么?
hive是基於Hadoop的一個數據倉庫工具,可以將結構化的數據文件映射為一張數據庫表,並提供簡單的sql查詢功能,可以將sql語句轉換為mapreduce任務進行運行。
Hive中的表是純邏輯表,就只是表的定義等,即表的元數據。本質就是Hadoop的目錄/文件,達到了元數據與數據存儲分離的目的
Hive本身不存儲數據,它完全依賴HDFS和MapReduce
Hive的內容是讀多寫少,不支持對數據的改寫和刪除(0.14版本以后支持更新,但是得開啟,默認關閉。由此可見hive不適合更新,因為hdfs也不適合修改!hdfs數據要修改,要么就是刪除,要么就是追加,考慮到性能,大數據不建議頻繁修改和刪除)
Hive中沒有定義專門的數據格式,由用戶指定,需要指定三個屬性:
– 列分隔符 : 空格, \t , \001
– 行分隔符: \n
– 讀取文件數據的方法: TextFile ,SquenceFile,RCFile
TextFile(優點:可讀性好。缺點:占內存空間,磁盤開銷大)--------python,Streaming開發一般是這種格式
SquenceFile(二進制,是hadoop提供的一種二進制文件,<key,value>形式序列化到文件中,Java Writeable接口進行序列化和反序列化)------java開發一般是這種格式
RCFile(是Hive專門推出的,一種面向列的數據格式)---------實際上在mapreduce的map階段遠程拷貝的時候,本質是拷貝block,但是block依然是整個的數據,block沒辦法具體區分哪一個列,讀過來就是全讀,所以性能並不一定比TextFile好
為什么選擇hive?
看一個wordcount
select word,count(*) form (select exploed(sentence, ' ') as word form article) t group by word
一行sql實現了一個單詞計數,大量節省開發和學習成本,而且便於修改
Hive 中 的 sql 與傳統 sql 區 別:
函數:
UDF:直接應用於select語句,通常查詢的時候,需要對字段做一些格式化處理(例如:大小寫轉換,比如表里都是小寫,但是就想顯示全是大寫)
特點:一進一出,一對一的關系
UDAF:多對一的關系,通常用於group by階段
UDTP:一對多
讀時模式:只有hive讀的時候才會檢查,解析字段和schema(數據結構的表達)
優點:load data非常迅速,因為在寫的過程中不需要解析數據
寫時模式:
優點:讀的時候會得到優化
缺點:寫的慢,需要建立一些索引,壓縮,數據一致性,字段檢查等...
與傳統關系數據特點比較:
hive和關系數據庫存儲文件的系統不同,hive使用的是hadoop的HDFS(hadoop的分布式文件系統),關系數據庫則是服務器本地的文件系統
hive使用的計算模型是mapreduce,而關系數據庫則是自己設計的計算模型
關系數據庫都是為實時查詢的業務進行設計的,而hive則是為海量數據做數據挖掘設計的,實時性很差
Hive很容易擴展自己的存儲能力和計算能力,這個是繼承hadoop的,而關系數據庫在這個方面要比數據庫差很多
Hive體系架構:
分為三個部分:
用戶接口:
CLI:client(Hive 的客戶端,用戶連接至 Hive Server,一般是linux下)進行交互執行sql,直接與Driver進行交互。
JDBC:Hive提供JDBC驅動,作為JAVA的API:JDBC是通過Thrift Server來接入,然后發給Driver
GUI:通過瀏覽器訪問 Hive
語句轉換(Driver------->hive本身並不會生成mapreduce,而是通過一個執行計划來執行mapreduce(xml----->mapper,reducer模塊)):
解析器:生成抽象語法樹
語法分析器:驗證查詢語句
邏輯計划生成器(包括優化器):生成操作符樹
查詢計划生成器:轉換為map-reduce任務
元數據:
metastore------>是一個獨立的關系型數據庫,默認的數據庫是derby(單用戶常用)。真正的生產都是遠程服務模式----->mysql
數據存儲:
Hive數據以文件形式存儲在HDFS的指定目錄下
Hive語句生成查詢計划,由MapReduce調用執行
Hive數據管理:
hive的表本質就是Hadoop的目錄/文件
– hive默認表存放路徑一般都是在你工作目錄的hive目錄里面,按表名做文件夾分開,如果你有分區表的話,分區值是子文件夾,可以直接在其它的M/R job里直接應用這部分數據
Hive有四種數據模型:
數據表:
Table:內部表
External Table:外部表
分區表:
Partition
Bucket
Table:
和傳統數據庫概念基本一致,都是一個數據表,但是每一個table在hive中都會有一個目錄來存取數據
例如: 有表user ,因為hive不存儲數據,都是在hdfs上,所以路徑就在/warehouse/user/(注意:user不是一個文件,是一個目錄)
Partition:
相當於分桶
好處:通常查詢的時候會掃描整個表的內容,那就會消耗很多的時間
例如:select xxx form table where date='2019-03-07' limit 100 通常查詢時候都會有where條件,但是這樣查詢也會掃描8,9....等等的數據,但是8,9號的數據對我們要查的來說完全沒有意義,我們只需要7號的數據
引入partition能大大優化性能,分區表需要在創建表的時候引入一個partition的分區的空間,一個表可以有一個或多個分區,然后以單獨的文件夾的形式存在表的文件夾下面(wherehorse/user/partition)
通常什么字段能做為分區字段呢?
不是所有的字段都適合做分區
1.通常這個字段是經常在where條件中做過濾用的
2.取值范圍有點集合的字段(假設用戶名做分區,那將會有無數個小文件,然而小文件會占用namenode內存區域,關於hdfs為什么不適合大量存儲小文件,如果有時間會寫hdfs的內容)
假設要對一天的數據做統計:
那就按照天做分區 day=20190307 路徑位置/warehouse/table/20190307/
查詢的時候where條件就成了一個文件夾了,然后對里面的內容做查詢就可以了,不用查詢其他的天數了
當多個字段做分區的時候,會按照笛卡爾迪的形式 action=insight, day=20190307 路徑/warehouse/table/insight/20190307
Bucket:
開啟bucket:set hive.enforce.bucketing = true
Hive會針對某一個列進行桶的組織,通常對列值做hash
假設:想存userid,然后這張表太大了,但是又想存數據,又不想突破一張表的的上限
分庫:把一張表拆分成多個表
例如:分32庫,userid%32=桶號
表名:table
分庫后表名:table_0,table_1,table_2,table_3......table_32
每張表都不會重復,因為按照userid做的分桶
路徑/warehouse/table/partition/part-00000
bucket有什么作用呢?
1.優化查詢
2.方便采樣
假設兩張表,id相同,分區相同,當做join的時候,只需要join目標id相同的分桶就可以,其他的桶不需要理會,性能大大優化
兩個分區表做join,他會自動激活map端的 (map-side Join)
Hive的內部表和外部表:
內部表:create table
外部表:create external table
內部表和外部表的區別:
內部表刪除,表結構和數據都刪除
外部表刪除,只刪除表結構,不刪除數據(刪除外部表怎么恢復?重新創建表)
- 在導入數據到外部表,數據並沒有移動到自己的數據倉庫目錄下,也就是說外部表中的數據並不是由它自己來管理的!而表則不一樣;
- 在刪除表的時候,Hive將會把屬於表的元數據和數據全部刪掉;而刪除外部表的時候,Hive僅僅刪除外部表的元數據,數據是不會刪除的!
Hive的數據類型:
基礎類型:
• TINYINT
• SMALLINT
• INT
• BIGINT
• BOOLEAN
• FLOAT
• DOUBLE
• STRING
• BINARY(Hive 0.8.0以上才可用)
• TIMESTAMP(Hive 0.8.0以上才可用)
復合類型:
• Arrays:ARRAY<data_type>
• Maps:MAP<primitive_type, data_type>
• Structs:STRUCT<col_name: data_type[COMMENT col_comment],……>
• Union:UNIONTYPE<data_type, data_type,……>