hive是基於Hadoop的一個數據倉庫工具,能夠將結構化的數據文件映射爲一張數據庫表,並提供簡單的sql查詢功能,能夠將sql語句轉換爲MapReduce任務進行運行。 其優勢是學習成本低,能夠經過類SQL語句快速實現簡單的MapReduce統計,沒必要開發專門的MapReduce應用,十分適合數據倉庫的統計分析。mysql
Hive on Spark 和 Hive on Tezsql
Hive 的結構如圖所示
主要分爲如下幾個部分:shell
支持的基本類型有數據庫
數據類型 | 所佔字節 | 開始支持版本 |
---|---|---|
TINYINT | 1byte,-128 ~ 127 | |
SMALLINT | 2byte,-32,768 ~ 32,767 | |
INT | 4byte,-2,147,483,648 ~ 2,147,483,647 | |
BIGINT | 8byte,-9,223,372,036,854,775,808 ~ 9,223,372,036,854,775,807 | |
BOOLEAN | ||
FLOAT | 4byte單精度 | |
DOUBLE | 8byte雙精度 | |
STRING | ||
BINARY | 從Hive0.8.0開始支持 | |
TIMESTAMP | 從Hive0.8.0開始支持 | |
DECIMAL | 從Hive0.11.0開始支持 | |
CHAR | 從Hive0.13.0開始支持 | |
VARCHAR | 從Hive0.12.0開始支持 | |
DATE | 從Hive0.12.0開始支持 | |
ARRAY | ARRAY類型是由一系列相同數據類型的元素組成,這些元素能夠經過下標來訪問。好比有一個ARRAY類型的變量fruits,它是由['apple','orange','mango']組成,那麼咱們能夠經過fruits[1]來訪問元素orange,由於ARRAY類型的下標是從0開始的; | |
MAP | MAP包含key->value鍵值對,能夠經過key來訪問元素。好比」userlist」是一個map類型,其中username是key,password是value;那麼咱們能夠經過userlist['username']來獲得這個用戶對應的password; | |
STRUCT | STRUCT能夠包含不一樣數據類型的元素。這些元素能夠經過」點語法」的方式來獲得所須要的元素,好比user是一個STRUCT類型,那麼能夠經過user.address獲得這個用戶的地址。 | |
UNION | UNIONTYPE,他是從Hive 0.7.0開始支持的。 |
建立一個複合類型的表apache
CREATE TABLE employees ( name STRING, salary FLOAT, subordinates ARRAY<STRING>, deductions MAP<STRING, FLOAT>, address STRUCT<street:STRING, city:STRING, state:STRING, zip:INT>) PARTITIONED BY (country STRING, state STRING)
建立數據庫
CREATE DATABASE [IF NOT EXISTS] userdb
刪除數據庫
DROP DATABASE [IF EXISTS ]userdb
數組
類型 | 內部表 | 外部表 |
---|---|---|
數據來源 | 與數據庫中的 Table 在概念上是相似 | 指向已經在 HDFS 中存在的數據,能夠建立 Partition |
數據存放 | 每個 Table 在 Hive 中都有一個相應的目錄存儲數據。例如,一個表 test,它在 HDFS 中的路徑爲:/ warehouse/test。 warehouse是在 hive-site.xml 中由 ${hive.metastore.warehouse.dir} 指定的數據倉庫的目錄 | 它和 內部表 在元數據的組織上是相同的,而實際數據的存儲則有較大的差別,能夠存放於各個不一樣的目錄 |
數據處理 | 全部的 Table 數據都保存在這個目錄中,內部表的建立過程和數據加載過程(這兩個過程能夠在同一個語句中完成),在加載數據的過程當中,實際數據會被移動到數據倉庫目錄中 ,以後對數據訪問將會直接在數據倉庫目錄中完成。 刪除表時,表中的數據和元數據將會被同時刪除 | 外部表 只有一個過程,加載數據和建立表同時完成,並不會移動到數據倉庫目錄中,只是與外部數據創建一個連接。當刪除一個外部表時,僅刪除該連接 |
內部表:緩存
CREATE TABLE [IF NOT EXISTS] worker1(id INT,name STRING)ROW FORMAT DELIMITEDFIELDS TERMINATED BY ',' --列分隔符LINES TERMINATED BY '\n' --行分隔符STORED AS ORC --存儲格式,支持TextFile、Parquet、RCFile和ORC FileLOCATION '/user/hive/test/worker1'--數據存放路徑
外部表:app
CREATE EXTERNAL TABLE [IF NOT EXISTS] worker2(id INT,name STRING)ROW FORMAT DELIMITEDFIELDS TERMINATED BY ',' --列分隔符LINES TERMINATED BY '\n' --行分隔符STORED AS ORC --存儲格式,支持TextFile、Parquet、RCFile和ORC FileLOCATION '/user/hive/test/worker2'--數據存放路徑
內部表與外部表相互轉換yii
alter table worker1 set TBLPROPERTIES ('EXTERNAL'='TRUE'); --內部錶轉外部表 alter table worker1 set TBLPROPERTIES ('EXTERNAL'='FALSE'); --外部錶轉內部表
動態建立表
動態建立表一般會用在建立臨時表,又不想使用緩存(固然,hive不支持緩存,SparkSQL中支持)的狀況
不修改字段名與類型:ide
CREATE TABLE worker_tempSTORED AS orcAS SELECT * FROM worker2
DROP TABLE [IF EXISTS] table_name
若是是外部表,而且有location,則須要經過hdfs刪除對應的目錄才能徹底刪除數據
TRUNCATE TABLE table_name;
ALTER TABLE employee RENAME TO emp;
hive> ALTER TABLE worker1 RENAME TO worker;OKTime taken: 1.156 secondshive> show tables;OKworkerworker2
下表包含employee表的字段,它顯示的字段要被更改(粗體)。
字段名 | 從數據類型轉換 | 更改字段名稱 | 轉換爲數據類型 |
---|---|---|---|
eid | int | eid | int |
name | String | ename | String |
salary | Float | salary | Double |
designation | String | designation | String |
下面查詢重命名使用上述數據的列名和列數據類型:
修改字段名
ALTER TABLE employee CHANGE name ename String
如:
hive> ALTER TABLE worker1 CHANGE name ename StringOKTime taken: 0.398 secondshive> desc worker1;OKid intename string
修改字段類型
ALTER TABLE employee CHANGE salary salary Double
如:
hive> ALTER TABLE worker1 CHANGE ename name varchar(20);OKTime taken: 0.472 secondshive> desc worker1;OKid int name varchar(20)
ALTER TABLE employee ADD COLUMNS ( dept STRING COMMENT 'Department name',--COMMENT增長註釋test String)
如
hive> ALTER TABLE worker1 ADD COLUMNS ( > dept STRING > );OKTime taken: 0.372 secondshive> desc worker1;OKid int name varchar(20) dept string Time taken: 0.309 seconds, Fetched: 3 row(s)
這個功能一般和增長列的功能一塊兒用。
由於Hive增長列只能在最後的一個Column後面增長,假如我想在中間插入一列怎麼辦呢?
可使用
ALTER TABLE table_name CHANGE [COLUMN] col_old_name col_new_name column_type [COMMENT col_comment] [FIRST|AFTER column_name]
因爲hive文件並無修改,只是至關於修改了字段名字而已,數據並無相應的移動。
所以,此方法適用於已建表,後續會從新刷新數據的狀況;或者空表。
目前貌似移除了這個功能
ALTER TABLE worker1 DROP COLUMN test1
ALTER TABLE worker1 REPLACE COLUMNS ( id INT, name String);
上面這條sql執行失敗,提示 SerDe may be incompatible
ALTER TABLE worker1 CHANGE COLUMN c c string AFTER a;
desc worker1
show create table worker1
desc formatted worker1
ALTER TABLE worker1 SET FILEFORMAT textFile
show functions
Hive不支持單句插入的語句,必須批量,因此不要期望能用insert into workers values (1,'jack') 這樣的語句插入數據。hive支持的插入數據的方式有兩種:
先創建一個叫 worker.csv的文件,內容爲
1,jack2,terry3,michael
使用LOAD DATA 導入到Hive的表中
LOAD DATA LOCAL INPATH '/home/root/workers.csv' INTO TABLE workers1;
LOAD DATA LOCAL INPATH
跟 LOAD DATA INPATH
的區別是一個是從你本地磁盤上找源文件,一個是從hdfs上找文件LOAD DATA LOCAL INPATH '/home/root/workers.csv' OVERWRITE INTO TABLE workers1
;INSERT [OVERWRITE] INTO TABLE works2select * from test
若是有分區(稍後咱們會講到)
INSERT INTO [OVERWRITE] TABLE table_name1 PARTITION(partition_name1 data, partition_name2 data, … )SELECT select_statement FROM from_statement;
分區表是用來加速查詢的,好比你的數據很是多,可是你的應用場景是基於這些數據作日報表,那你就能夠根據日進行分區,當你要作2014-05-05的報表的時候只須要加載2014-05-05這一天的數據就好了。
DROP TABLE IF EXISTS employee;CREATE EXTERNAL TABLE IF NOT EXISTS employee(id INT,name STRING,dept String,year int)PARTITIONED BY(p_year int)--指定分區,能夠包含多級分區ROW FORMAT DELIMITEDFIELDS TERMINATED BY ',' --列分隔符LINES TERMINATED BY '\n' --行分隔符STORED AS textFile --存儲格式,支持TextFile、Parquet、RCFile和ORC FileLOCATION '/user/hive/test/employeedata'--數據存放路徑
SHOW PARTITIONS employee;
DESC FORMATTED table_name partition (month = ‘2015-01’ , day = '2015-01-25′)
INSERT INTO TABLE table_name PARTITION PARTITION(p_column = ...)SELECT * FROM other_table_name;
INSERT OVERWRITE TABLE table_name PARTITION PARTITION(p_column = ...)SELECT * FROM other_table_name;
ALTER TABLE table_name ADD [IF NOT EXISTS ] PARTITION(p_column = ...) LOCATION "/user/root/test"
如:
ALTER TABLE employee ADD IF NOT EXISTS PARTITION(p_year = 2012) LOCATION "/user/hive/test/employeedata/2012";ALTER TABLE employee ADD IF NOT EXISTS PARTITION(p_year = 2013) LOCATION "/user/hive/test/employeedata/2013";
ALTER TABLE table_name PARTITION (p_date="2015-12-12") RENAME TO PARTITION (p_date="2015-12-13");
ALTER TABLE table_name DROP [IF EXISTS] PARTITION partition_spec, PARTITION partition_spec,...;
在hive中能夠直接使用分區進行查詢和計算操做,因爲加入了分區,使得hive處理數據時能夠讀取指定分區的內容,而不用遍歷全表,所以極大的加快了查詢速度
如:
select * from employee where p_year = 2013;結果:+--------------+----------------+----------------+----------------+------------------+--+| employee.id | employee.name | employee.dept | employee.year | employee.p_year |+--------------+----------------+----------------+----------------+------------------+--+| 3 | kaleel | SC | 2013 | 2013 || 4 | Prasanth | SC | 2013 | 2013 |+--------------+----------------+----------------+----------------+------------------+--+
桶表是根據某個字段的hash值,來將數據扔到不一樣的「桶」裏面。外國人有個習慣,就是分類東西的時候擺幾個桶,上面貼不一樣的標籤,因此他們取名的時候把這種表形象的取名爲桶表。桶表表專門用於採樣分析
把表(或者分區)組織成桶(Bucket)有兩個理由:
(1)得到更高的查詢處理效率。桶爲表加上了額外的結構,Hive 在處理有些查詢時能利用這個結構。具體而言,鏈接兩個在(包含鏈接列的)相同列上劃分了桶的表,可使用 Map 端鏈接 (Map-side join)高效的實現。好比JOIN操做。對於JOIN操做兩個表有一個相同的列,若是對這兩個表都進行了桶操做。那麼將保存相同列值的桶進行JOIN操做就能夠,能夠大大較少JOIN的數據量。
(2)使取樣(sampling)更高效。在處理大規模數據集時,在開發和修改查詢的階段,若是能在數據集的一小部分數據上試運行查詢,會帶來不少方便。
CREATE TABLE b_student(id INT, name STRING)PARTITIONED BY(dt STRING, country STRING)CLUSTERED BY(id) --按照哪一個字段分桶SORTED BY(name) INTO 4 BUCKETS --分紅幾個桶 row format delimited fields TERMINATED BY ',';
建立
Array:create table login_array(ip string,uid array<bigint>)partitioned by (dt string)row format delemited fields terminated by ','--列分隔符collection items terminated by '|' --數組分隔符stored as textfile;
使用
select ip uid[0] from login_array where dt='20130101';--使用數組下標訪問select ip,size(uid) from login_array where dt='20130101';--查看數組長度select * from login_array where array_contains(uid,'31050007');--查找數組
建立
Map:create table map_test_raw(ip string,request Map<string,string>)row format delemited fields terminated by ',' --列分隔符collection items terminated by '|' --Map集合分隔符map keys terminated by '=' --Key與value分隔符stored as textfile;
使用
select request['src'] from map_test_raw;
根據用戶的需求建立視圖。能夠將任何結果集數據保存爲一個視圖。視圖在Hive的用法和SQL視圖用法相同。它是一個標準的RDBMS概念。咱們能夠在視圖上執行全部DML操做。
CREATE VIEW worker_view ASSELECT * FROM worker2WHERE id>2;
DROP VIEW worker_view
索引也不過是一個表上的一個特定列的指針。建立索引意味着建立一個表上的一個特定列的指針。
CREATE INDEX worker_index ON TABLE worker2(id)AS 'org.apache.hadoop.hive.ql.index.compact.CompactIndexHandler'WITH DEFERRED REBUILD
SHOW INDEX ON worker2;
DROP INDEX worker_index ON worker2;
除了視圖之外,還可使用數據緩存的方式來保存某一結果集,只不過視圖是將結果集保存在hive中,使用的時候仍舊運行了一次查詢。而緩存則是將數據保存在了內存中,一般適用於須要屢次使用的數據查詢;可是,cache table的語法只能在Spark SQl中使用
整表緩存
sql=CACHE TABLE cache_worker AS SELECT * FROM worker2
DataFrame=hiveCtx.cacheTable("worker2")
或
hiveCtx.sql("SELECT * FROM worker2").cache()[或.persist()]
緩存部分數據
sql=CACHE TABLE cache_worker AS SELECT * FROM worker2 where id>1
DataFrame=hiveCtx.sql("SELECT * FROM worker2 where id>1").cache()[或.persist()]
該條語句對應了
sql=DROP TABLE cache_worker
DataFrame=hiveCtx.uncacheTable(cache_worker)
或dataframe.unpersist()
參考連接Hive教程