一、hive基礎概念
1、Hive是什么
Hive 是建立在 Hadoop 上的數據倉庫基礎構架。它提供了一系列的工具,可以用來進行數據提取轉化加載(ETL ),這是一種可以存儲、查詢和分析存儲在 Hadoop 中的大規模數據的機制。Hive 定義了簡單的類 SQL 查詢語言,稱為 HQL ,它允許熟悉 SQL 的用戶查 詢數據。同時,這個語言也允許熟悉 MapReduce 開發者的開發自定義的 mapper 和 reducer 來處理內建的 mapper 和 reducer 無法完成的復雜的分析工作。
Hive是SQL解析引擎,它將SQL語句轉譯成M/R Job然后在Hadoop執行。
Hive的表其實就是HDFS的目錄,按表名把文件夾分開。如果是分區表,則分區值是子文件夾,可以直接在M/R Job里使用這些數據。
Hive相當於hadoop的客戶端工具,部署時不一定放在集群管理節點中,可以放在某個節點上
2、hive與傳統數據庫比較
3、Hive的存儲格式
Hive的數據存儲基於Hadoop HDFS。
Hive沒有專門的數據文件格式,常見的有以下幾種。 TEXTFILE SEQUENCEFILE AVRO RCFILE ORCFILE PARQUET
4、Hive操作客戶端
二、hive基礎語法(hive基礎語法與MySQL差不多)
1、建庫,刪庫;
create database 庫名;
切換test1數據庫:
use test1;
刪庫
DROP DATABASE IF EXISTS ycc ;(刪除空數據庫)
DROP DATABASE IF EXISTS ycc CASCADE;(刪除庫之前清空庫中表)
2、建表;
create [EXTERNAL] table students ( id bigint, name string, age int comment, gender string, clazz string ) PARTITIONED BY ( 非必選;創建分區表 dt string) clustered by (userid) into 3000 buckets // 非必選;分桶子 ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t' // 必選;指定列之間的分隔符 STORED AS rcfile // 非必選;指定文件的讀取格式,默認textfile格式 location '/testdata/'; //非必選;指定文件在hdfs上的存儲路徑,如果已經有文件,會自動加載 ,默認在hive的warehouse下
CREATE [EXTERNAL] TABLE [IF NOT EXISTS] table_name // 定義字段名,字段類型 [(col_name data_type [COMMENT col_comment], ...)] // 給表加上注解 [COMMENT table_comment] // 分區 [PARTITIONED BY (col_name data_type [COMMENT col_comment], ...)] // 分桶 [CLUSTERED BY (col_name, col_name, ...) // 設置排序字段 升序、降序 [SORTED BY (col_name [ASC|DESC], ...)] INTO num_buckets BUCKETS] [ // 指定設置行、列分隔符 [ROW FORMAT row_format] // 指定Hive儲存格式:textFile、rcFile、SequenceFile 默認為:textFile [STORED AS file_format] | STORED BY 'storage.handler.class.name' [ WITH SERDEPROPERTIES (...) ] (Note: only available starting with 0.6.0) ] // 指定儲存位置 [LOCATION hdfs_path] // 跟外部表配合使用,比如:映射HBase表,然后可以使用HQL對hbase數據進行查詢,當然速度比較慢 [TBLPROPERTIES (property_name=property_value, ...)] (Note: only available starting with 0.6.0) [AS select_statement] (Note: this feature is only available starting with 0.5.0.)
A、全部使用默認格式
create table students ( id bigint, name string, age int, gender string, clazz string ) ROW FORMAT DELIMITED FIELDS TERMINATED BY ','; // 必選,指定列分隔符
B、
create table students2 ( id bigint, name string, age int, gender string, clazz string ) ROW FORMAT DELIMITED FIELDS TERMINATED BY ',' LOCATION '/input1'; // 指定Hive表的數據的存儲位置,一般在數據已經上傳到HDFS,想要直接使用,會指定Location,通常Locaion會跟外部表一起使用,內部表一般使用默認的location
C、
create table students3 ( id bigint, name string, age int, gender string, clazz string ) ROW FORMAT DELIMITED FIELDS TERMINATED BY ',' STORED AS rcfile; // 指定儲存格式為rcfile,inputFormat:RCFileInputFormat,outputFormat:RCFileOutputFormat,如果不指定,默認為textfile,注意:除textfile以外,其他的存儲格式的數據都不能直接加載,需要使用從表加載的方式。
D、
create table students4 as select * from students2;
create table students5 like students;
2.1、內部表:
1、內部表基礎建表語句一:(默認指定文件類型為TextFile,HDFS路徑為/user/hive/warehouse/庫/下)
格式:
create table 表名 ( 字段名1 字段類型1, 字段名2 字段類型2, ... ) ROW FORMAT DELIMITED FIELDS TERMINATED BY '分隔符'; // 必選指定列之間的分隔符
2、內部表基礎建表語句二:(HDFS路徑為/user/hive/warehouse/庫/下)
格式:
create table 表名 ( 字段名1 字段類型1, 字段名2 字段類型2, ... ) ROW FORMAT DELIMITED FIELDS TERMINATED BY '分隔符' // 必選指定列之間的分隔符 STORED AS file_format;
概述:
STORED AS:指定具體的從HDFS獲取數據的格式,格式不匹配無法獲取(默認為TextFile)
3、內部表基礎建表語句三:(HDFS路徑為/user/hive/warehouse/庫/下)
格式:
create table 表名 ( 字段名1 字段類型1, 字段名2 字段類型2, ... ) ROW FORMAT DELIMITED FIELDS TERMINATED BY '分隔符' // 必選指定列之間的分隔符 STORED AS file_format
location 'HDFS路徑';
概述:
location:表示指定hive數據在hdfs的路徑, 如果路徑不存在會自動創建,存在就直接綁定,不能通過hdfs路徑判斷是否是hive表
注意:
默認情況下 刪除表會把數據也刪除
2.2、外部表external
格式:
create external table 表名 ( 字段名1 字段類型1, 字段名2 字段類型2, ... ) ROW FORMAT DELIMITED FIELDS TERMINATED BY '分隔符' // 必選指定列之間的分隔符 STORED AS file_format
location 'HDFS路徑';
注意:
刪除外部表不會刪除HDFS上的元數據
2.3、內部表和外部表的區別
hdfs上創建目錄,上傳數據文件
指定創建的路徑建表
刪除表以后元數據對比
刪除表
drop table students_internal;
刪除外部表的時候,只會刪除表的元數據,不會刪除表中的數據(HDFS上的文件)
一般在公司中,使用外部表多一點,因為數據可以需要被多個程序使用,避免誤刪,通常外部表會結合location一起使用外部表還可以將其他數據源中的數據映射到 hive中,比如說:hbase,ElasticSearch......
3、加載數據(上傳到hive表,以文件的方式上傳)
a、上傳數據方式1:
格式:
hadoop dfs -put linux路徑 hdfs路徑
b、上傳數據方式2:(直接在hive命令行操作)
格式:
dfs -put linux路徑 hdfs路徑
優點:比在hadoop操作hdfs快的多
c、上傳數據方式3:(直接在hive命令行操作)
格式:
load data inpath '/HDFS路徑' into 表名(自動找到hdfs的路徑)
注意:對於hive來說是加載
對於HDFS來說是移動
d、上傳數據方式4:(直接在hive命令行操作)
格式:
load data local inpath '/本地路徑' into 表名(自動找到本地的路徑)
注意:從本地上傳數據
4、加載數據(表對表,將數據轉換成與之對應的格式)
create table IF NOT EXISTS students_test1 as select * from students //這種加載創建表不能指定格式
insert [overwrite] into table students_test2 select * from students;
打開查看students表中內容不能直接查看明文
overwrite和into的區別
、
5、分區(以目錄的形式對數據分割,避免全局掃描)
注意:分區字段和普通字段沒有什么區別,所以不能和普通字段名重復
建表語句:
CREATE TABLE students_pt(id bigint,name string,age int comment,gender string,clazz string ) PARTITIONED BY (year STRING, month STRING) ROW FORMAT DELIMITED FIELDS TERMINATED BY ',';
用法:
select * from students_pt where year=“2021” and month =“01”
未分區前
分區以后:
create external table studentsPation( id bigint, name string, age int, gender string, clazz string ) PARTITIONED BY (dt string) ROW FORMAT DELIMITED FIELDS TERMINATED BY ','; STORED AS rcfile;
添加分區: alter table 表名 add partition(分區字段='值'); 刪除分區: alter table 表名 drop partition(分區字段='值'); 查看分區: select DISTINCT 分區字段 from 表;//建議使用 show partitions 表; 插入數據: load data local inpath '路徑' into table 表名 partiton(分組字段='值'); 分區不存在自動創建
增加分區:
向指定分區上傳數據
6、動態分區
有的時候我們原始表中的數據里面包含了 ''日期字段 dt'',我們需要根據dt中不同的日期,分為不同的分區,將原始表改造成分區表。
> hive默認不開啟動態分區
> 動態分區:根據數據中某幾列的不同的取值 划分 不同的分區
# 表示開啟動態分區 hive> set hive.exec.dynamic.partition=true; # 表示動態分區模式:strict(需要配合靜態分區一起使用)、nostrict # strict: insert into table students_pt partition(dt='anhui',pt) select ......,pt from students; hive> set hive.exec.dynamic.partition.mode=nostrict; # 表示支持的最大的分區數量為1000,可以根據業務自己調整 hive> set hive.exec.max.dynamic.partitions.pernode=1000;
建立原始表並加載數據
create table students( id bigint, name string, age int, gender string, clazz string, dt string ) ROW FORMAT DELIMITED FIELDS TERMINATED BY ',';
建立分區表並加載數據
create table students01 ( id bigint, name string, age int, gender string, clazz string ) PARTITIONED BY(dt string) ROW FORMAT DELIMITED FIELDS TERMINATED BY ',';
使用動態分區插入數據
// 分區字段需要放在 select 的最后,如果有多個分區字段 同理,它是按位置匹配,不是按名字匹配 insert into table students01 partition(dt) select id,name,age,gender,clazz,dt from students_dt;(按時間分區) // 比如下面這條語句會使用age作為分區字段,而不會使用student_dt中的dt作為分區字段 insert into table students01 partition(dt) select id,name,age,gender,dt,age from students_dt;(按年齡分區)
7、多級分區(分區最多三級分區)
案例:按年月進行的動態分區
create table students2( id bigint, name string, age int, gender string, clazz string, year string, month string ) ROW FORMAT DELIMITED FIELDS TERMINATED BY ',';
創建分區表:
create table students02( id bigint, name string, age int, gender string, clazz string ) PARTITIONED BY (dt_year string,dt_month string) ROW FORMAT DELIMITED FIELDS TERMINATED BY ',';
Hive會自動根據bucket個數自動分配Reduce task的個數 Reduce個數與bucket個數一致
格式: create external table 表名 ( 字段名1 字段類型1, 字段名2 字段類型2, ... )clustered by (分桶字段) into 分桶數量 buckets ROW FORMAT DELIMITED FIELDS TERMINATED BY '分隔符' // 必選指定列之間的分隔符 注意: 分桶字段來源普通字段,分同數量是明確的
8.1、開啟分桶開關
hive>set hive.enforce.bucketing=true;
8.2、創建分桶表
create table students03( id bigint, name string, age int, gender string, clazz string ) clustered by (clazz) into 12 buckets ROW FORMAT DELIMITED FIELDS TERMINATED BY ',';
8.3、加載數據
分析:發現有的分桶后有的文件是空,有的文件clazz占了幾個,這是為什么呢
因為分桶機制是按key機制去區分,這里以clazz為key作為區分,正常來說每個reduce處理一個key,但是處理機制對key值進行取值取余處理,可能兩個班級的處理之后相同,就會進入到一個reduce中,那么就會有reduce為空
8.5、好處:
1、減少map端數據傾斜,資源平均處理,數據跑的快一點
2、方便數據抽樣,在每個分桶抽取數據
不常用,因為對文件進行切分產生過多的小文件