定義
hive是一個建構在hadoop上的資料倉庫架構。可以将結構化的資料檔案映射為一張資料庫表,并提供完整的sql查詢功能,可以将sql語句轉換為mapreduce任務進行運作。 其優點是學習成本低,可以通過類sql語句快速實作簡單的mapreduce統計,不必開發專門的mapreduce應用,十分适合資料倉庫的統計分析。(來自百度百科~~)
metastore
metastore是hive中繼資料的集中存放地,metastore包括兩部分:服務和背景資料的存儲。預設情況下,中繼資料存儲在derby資料庫執行個體中。由于是本地資料庫且不支援并發通路,故多作為練手使用。還一種使用其他資料庫的方式稱為“local metastore”,支援并發通路,但metestore服務仍然和hive服務運作在同一個程序中,故稱之為本地metastore。還有第三種方式:“remote metastore”,metastore無武器和hive服務運作在不同的程序内,可以提供更好的可管理性和安全性。(怎麼配local metastore和remte metastore先不搞了,先拿預設方式練手為主~)
和傳統資料庫的比較
最本質的一點,hive依賴于hdfs和mapreduce!
在傳統資料庫裡,表的模式是在資料加載時強制确定的(寫時模式,schema on write),而hive對資料的驗證卻在查詢時進行(讀時模式,schema on read);讀時模式有利于資料加載,基本上就是純粹的複制粘貼,且更加靈活,可以以各種不同模式來分析資料。寫時模式有利于提升查詢性能,因為可以建索引,壓縮資料等。
hive不支援更新,事務和索引。(暫時不支援吧,将來誰也說不準~)hive是用來以mr的方式操作hdfs資料的,在這種環境下,全表掃描(full-table scan)是常态操作,而表更新則是通過吧資料變換後放入新表實作。事務方面hive并沒有對表的并發通路做什麼處理,需要應用程式端自己在應用層實作。(比如類似spring事務)
hiveql
不完全支援sql-92标準,支援數值型,布爾型,字元串類型等原子類型;數組,映射,結構等複雜類型。
tinyint,smallint,int,bugint分别對應于java中的byte,short,int,long。
float,double直接對應float,double(廢話~)
string對應于string,而沒有其他資料庫中的 varchar,varchar2,char等類型。hive的string類似于其他資料庫中的varchar,但是不能聲明最長字元數,理論上string最長為2g。
資料類型轉換:
任何類型都可以隐式轉換為一個範圍更廣的類型,所有整數類型,float,string(這個有點奇怪)都可以隐式轉換為double,tinyint,smallint,int都可以隐式轉換為float,double最大,不能隐式轉換為任何類型。
可以使用cast執行顯式轉換,如果轉換失敗則傳回空值null。
複雜類型:
hive有3中複雜類型:array,map和struct;array,map和java中的類似;struct是一種記錄類型,封裝了一個命名的字段集合。複雜資料類型允許任意層次的嵌套。
操作:
“||” 不是字元串連接配接操作符,而是 “或”操作符,concat函數用來作為連接配接操作
表:
hive表格邏輯上由存儲的資料和描述表格中資料形式的相關中繼資料組成。資料存放在hdfs中,中繼資料(metastore)存放在關系資料庫中。
hive中的表分為托管表(managed table)和外部表(external table)兩種。托管表是預設情況,托管表會将資料移入hive的倉庫目錄(warehouse directory);外部表則直接到外部目錄通路資料。
相應的,如果是托管表,load操作将會複制資料到倉庫目錄,drop操作将會删除表資料和表的中繼資料,而外部表則需要在create操作時指定外部資料路徑,在drop操作時,隻删除中繼資料而不碰外部資料。外部表使用external關鍵字建立。
普遍的用法是把存放在hdfs中的初始資料集用作外部表使,用hive轉換後的資料存入托管表;反過來——外部表可以用作将托管表中的資料導出到hdfs以供其他應用程式使用。
分區和桶
分區的好處是對于同一分區内的資料進行查詢的時候将會非常高效,比如按年份分區,查某一年的資料隻需要到這個分區中檢索就行了。分區是在建立表的時候用 partitioned by 子句定義的。
在load資料的時候則需要指定分區值:
在檔案系統中,分區隻是表目錄下嵌套的子目錄。如按分區檢索資料其實就是按檔案系統目錄檢索資料了。
show partitions logs; 指令會傳回目前表中所有分區資訊。partitioned by 子句中的列是表中正式的列,稱為分區列。但是資料檔案并不包含這些列,因為在目錄中包含了。可以像普通列一樣使用分區列(partition column)。
桶可以獲得更高的查詢處理效率;桶可以使取樣操作更高效。使用clustered by 子句來制定劃分桶所用的列和要劃分的桶的個數。
桶對應于mr的輸出檔案分區:一個作業産生的桶(輸出檔案)和reduce任務個數相同。由于我本地隻有一個僞分布環境,隻能一個reduce,是以隻得到一個桶,一個桶~

桶檔案中包含在這個桶中的記錄資訊,劃分桶的規則是:hive對值進行哈希并将結果除以桶的個數取餘數,這樣任何一個桶裡都會有一個随機的使用者集合。
tablesample 子句對表進行取樣,這個子句會将查詢限定在表的一部分桶内,而不是使用整個表:
存儲格式
hive從兩個次元對表的存儲進行管理:“行格式”(row format)和“檔案格式”(file format)。行格式指行和一行中的字段如何存儲,行格式由serde定義(serializer-deserializer)
預設格式為分割的文本,每行存儲一個資料行。
二進制存儲格式:順序檔案和rcfile
hadoop的順序檔案格式是一種針對順序和記錄的通用二進制格式。在hive中,可以在create table 中通過聲明stored as sequencefile來使用順序檔案。使用順序檔案一個主要的優點是支援可分割的壓縮(splittable)。順序檔案時面相行的,這意味着同一行中的字段作為一個順序檔案記錄存儲在一起。
rcfile按列記錄檔案,rcfile把表分成行分片(row split),在每一個分片中先存所有行的第一列,再存第二列,以此類推。通過聲明stred as rcfile來使用rcfile存儲格式。
面向行的存儲格式對于那些隻通路表中一小部分行的查詢比較有效;面相列的存儲格式适合同僚處理一列中很多列的情況。
導入資料
create table ... as select
insert overwrite table
load data
三種格式,load data 和 insert overwrite table 上面都有示例了,ctas練手一個吧,還有插入partition的示例,多表插入
ctas操作是原子的,如果select查詢由于某種原因失敗,是不會建立新表的。
表的操作
drop表就跟其他sql一緻了, 如果是外部表,則隻删除中繼資料,外部資料不會受到影響。
查詢資料
排序和聚集:
hive的order by子句對資料進行排序,但是order by是通過隻用一個reducer來做到這一點的。對于大規模的資料集,效率非常低下。
在很多情況下,并不需要結果是全局排序。此時,可以使用hive的非标準的擴充sort by。
sort by:為每個reducer産生一個排序檔案;
distribute by x:確定x列相同的資料在同一個reduce分區中;
内連接配接:
hive 不支援 where sales.id=things.id 這樣的連接配接操作!
三種外連接配接:(左外,右外,全外)
半連接配接:
hive不支援in操作,但是可以使用left semi join 達到相同的效果:(sales表不能再select 後面出現,感覺類似exist了)
指定map連接配接:
如果有一個連接配接表小到足以放入記憶體,hive就可以把較小的表放入每個mapper的記憶體來執行連接配接操作。在hive中需要使用注釋來指定map連接配接:
子查詢:
hive隻支援子查詢出現在from子句中
視圖:貌似和其他資料庫中視圖沒啥差別,隻是儲存中繼資料,而不執行查詢,不物化資料。
使用外部腳本:
使用hadoop streaming,transform,map,reduce子句可以在hive中調用外部腳本
使用者自定義函數 (user-defined function,udf)
hive有三種udf:普通udf,使用者定義聚集函數udaf,使用者定義表生成函數udtf。
udf使用者操作單個資料行,産生一個資料行作為輸出,就像普通函數傳回一個傳回值;
udaf接受多個輸入資料行,産生一個輸出資料行,聚集函數好像都如此;
udtf作用于單個資料行,産生多個資料行(一個表)作為輸出。
(不想寫了~ 這幾個鳥函數決定使用到了再來研究了!!!)over