什麼是Hive?
Hive是建立在Hadoop上的,用來構建數據倉庫的工具,裏面有表的概念,可以使用SQL語句實現存儲、查詢和分析存儲在 HDFS上的數據,這些SQL語句在Hive中稱爲HQL,語法和SQL語句基本一樣。
由於數據是雜亂無章的,所以Hive需要一份關於這些數據的元數據來管理和操作這些數據。這份元數據包括:
元數據(
行的分隔符(在映射成表的時候知道在哪裏分行顯示)
字段分隔符(在映射成表的時候知道在哪裏分列顯示)
字段的類型
字段的名稱
)
在Hive中,我們把數據存儲在HDFS中,元數據默認存儲在Hive自帶的Derby數據庫中,由於Derby不能實現併發訪問,所以我們一般使用mysql進行替換。
Hive的原理
Hive 將用戶的HQL 語句進行解析,優化,最終把一個個的HQL語句轉換爲MapReduce 作業提交到Hadoop 集羣上,Hadoop進行作業的調度及監控,作業完成後將執行結果返回給用戶。所以,Hive並不進行計算,只是把HQL解析爲MapperReduce在HDFS集羣中運行而已,所以Hive的效率並不高。
Hive表的類型
hive中有5種表:
1. 內部表
數據默認存儲在/user/hive/warehouse,由hive自身管理,刪除內部表會同時刪除存儲數據和元數據。
建表方式一:
create table t1(
id INT,
name STRING,
age INT,
gfs ARRAY<STRING>,
address MAP<STRING,STRING>,
info STRUCT<country:String,province:String,shi:String>
)
ROW FORMAT DELIMITED
FIELDS TERMINATED BY ' '
COLLECTION ITEMS TERMINATED BY ','
MAP KEYS TERMINATED BY ':'
LINES TERMINATED BY '\n'
LOCATION "/test";//可以設置源數據的位置,若不設置默認就在Hive的工作目錄區
建表方式二:
create table gfstbl1 like gfstbl;只是創建表結構
建表方式三:
create table gfstbl2 AS SELECT id,name,gfs,address from gfstbl;
會創建相應的表結構,並且插入數據,相當於完整的賦值
加載數據:
load data local inpath '/root/gfs.txt' into table gfstbl;
查看錶描述信息:
DESCRIBE [EXTENDED|FORMATTED] table_name
EXTENDED極簡的方式顯示
FORMATTED格式化方式來顯示
DESCRIBE EXTENDED gfstbl;默認就是EXTENDED
DESCRIBE FORMATTED gfstbl;
插入數據的其他方式:
插入數據的方式:
1、insert 新數據
2、load
3、查詢其他表數據 insert 到新表中
模板:
INSERT INTO TABLE tablename1 [PARTITION (partcol1=val1, partcol2=val2 ...)]
select_statement1 FROM from_statement;
FROM from_statement
INSERT OVERWRITE TABLE tablename1 [PARTITION (partcol1=val1, partcol2=val2 ...)
[IF NOT EXISTS]] select_statement1
insert into rest select count(*) from table;
習慣寫法 from提前 減少SQL代碼的冗餘
from day_hour_table
insert into rest
select count(*) ;
2. 外部表
數據存儲位置由用戶自己指定,由HDFS管理,刪除外部表時僅僅會刪除元數據,存儲數據不會受到影響。
建表語句:
create external table wc_external
(word1 STRING,
word2 STRING)
ROW FORMAT DELIMITED
FIELDS TERMINATED BY ' '
location '/test/external'; location可加可不加,不加location默認是在hive的工作目錄區
3. 臨時表
在當前會話期間存在,會話結束後自動銷燬。
建表語句:
create TEMPORARY table ttabc(id Int,name String) 臨時表的聲明週期是一次會話
進入hive shell 創建一張表,關閉shell後,表丟失,臨時表不支持分區
4. 分區表
將數據按照某個字段或者關鍵字分成多個子目錄來存儲,防止暴力掃描全表。
靜態分區表:
create table day_hour_table (id int, content string) partitioned by (dt int,hour int)
ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t' ;
加載數據:
-- insert單條插入的方式往分區表中插入數據:
insert into day_hour_table partition(dt=9,hour=1) values(1,"a2 bc");
insert into day_hour_table partition(dt=9,hour=2) values(3,"a2 bc");
insert into day_hour_table partition(dt=8,hour=1) values(3,"a2 bc");
insert into day_hour_table partition(dt=8,hour=2) values(3,"a2 bc");
-- load批量插入的方式往分區表中插入數據:
load data local inpath "/root/ceshi" into table day_table partition (dt=10,hour=10);
刪除Hive分區表中的分區
ALTER TABLE day_table DROP PARTITION (dt=10,hour=10);
創建\添加分區
ALTER TABLE table_name ADD [IF NOT EXISTS] PARTITION partition_spec [LOCATION 'location']
[, PARTITION partition_spec [LOCATION 'location'], ...];
partition_spec:
: (partition_column = partition_col_value, partition_column = partition_col_value, ...)
-- 創建一個空分區:
ALTER TABLE day_hour_table ADD PARTITION (dt=10000, hour=2000);
-- 然後將數據上傳到空分區對應的目錄下,分區表中就會顯示數據
HDFS dfs -put ........
-- 創建一個空分區並且將空分區指向數據位置:
ALTER TABLE day_hour_table ADD PARTITION (dt=10000, hour=2000) location "/test"
動態分區表:
動態分區表和靜態分區表建表語句相同,插入數據的方式不同
set hive.exec.dynamic.partition=true;
set hive.exec.dynamic.partition.mode=nonstrict;
動態分區可以根據數據本身的特徵自動來劃分分區,load data …只是將數據上傳到HDFS指定目錄,所以我們需要使用from insert的方式插入數據hive纔會根據分區設置自動將數據進行分區。
5. 分桶表
將數據按照某個字段和桶的數量,對指定字段進行取模運算,拆分成多個小文件來存儲,模相同的存儲在同一個小文件中,提高join以及抽樣的效率。
set hive.enforce.bucketing=true;
分桶表是對列值取哈希值的方式,將不同數據放到不同文件中存儲
由列的哈希值除以桶的個數來決定每條數據劃分在哪個桶中
對於hive中每一個表、分區都可以進一步進行分桶
建表語句
CREATE TABLE psnbucket( id INT, name STRING, age INT)
CLUSTERED BY (age) INTO 4 BUCKETS
ROW FORMAT DELIMITED FIELDS TERMINATED BY ',';
插入數據
insert into table psnbucket select id, name, age from original;
抽樣:
select * from psnbucket tablesample(bucket 1 out of 4 on age);
分桶表+分區表:
CREATE TABLE psnbucket_partition( id INT, name STRING, age INT)
PARTITIONED BY(height DOUBLE)
CLUSTERED BY (age) INTO 4 BUCKETS
ROW FORMAT DELIMITED FIELDS TERMINATED BY ',';
插入數據:
insert into table psnbucket_partition partition(height) select id, name,
age,height from original;
多個分區中的對應的位置的小文件組成一個桶
插入數據:
insert into table psnbucket_partition partition(height) select id, name,
age,height from original;
多個分區中的對應的位置的小文件組成一個桶