目录
一、Hive数据类型
(一)Hive基本数据类型
(二)Hive的基本数据类型转换
(三)Hive集合数据类型
(四)文本文件数据编码
(五)读时模式
(六)Hive数据结构
二、DDL&DML命令
(一)数据库操作
1.创建数据库
2.查看数据库
3.修改数据库
4.删除数据库
5.切换(使用)指定数据库
(二)表操作
1.建表语法
2.内部表
3.外部表
4.内部表与外部表的转换
5.分区表
6.分桶表
7.修改表与删除表
(三)数据操作
1.数据导入
2.插入数据
3.数据导出
一、Hive数据类型
(一)Hive基本数据类型
类型 | 示例 | 类型 | 示例 |
TINYINT | 10 | SMALLINT | 10 |
INT | 10 | BIGINT | 100L |
FLOAT | 1.342 | DOUBLE | 1.234 |
DECIMAL | 3.14 | BINARY | 1010 |
BOOLEAN | TRUE | STRING | 'Book' or "Book" |
CHAR | 'YES' or "YES" | VARCHAR | 'Book' or "Book" |
DATE | '2013-01-31' | TIMESTAMP | '2020-01-31 00:13:00.345' |
(二)Hive的基本数据类型转换
参考下图,可以从下至上进行转换
任何整数类型都可以隐式转换为一个范围更广的类型。tinyint=>int;int=>bigint;
所有整数类型、float、string(都是数字)都可以隐式转换为Double;
tinyint、smallint、int=>float;
boolean不能转换;
select '1.0'+2; -- 3 select '88' > 888; select '1'+true;-- 报错,boolean不能转换 select cast('111' as int);-- 111
(三)Hive集合数据类型
(四)文本文件数据编码
在 vi 中输入特殊字符:
- (Ctrl + v) + (Ctrl + a) => ^A
- (Ctrl + v) + (Ctrl + b) => ^B
- (Ctrl + v) + (Ctrl + c) => ^C
^A / ^B / ^C 都是特殊的控制字符,使用 more 、 cat 命令是看不见的;可以使用cat - A file.dat
1.创建一个表
create table s1(
id int,
name string,
age int,
hobby array<string>,
score map<string,int>
);
2.XShell端创建文本文件
[root@lxm147 stufile]# cat -A /opt/stufile/s1.txt
666^Alisi^A18^Aread^Bgame^Ajava^C97^Bhadoop^C87$
3.上传数据
load data local inpath '/opt/stufile/s1.txt' into table s1;
select * from s1;
4.运行结果
(五)读时模式
在传统数据库中,在加载时发现数据不符合表的定义,则拒绝加载数据。数据在写入 数据库时对照表模式进行检查,这种模式称为 " 写时模式 " ( schema on write )。写时模式 -> 写数据检查 -> RDBMS ;Hive中数据加载过程采用 " 读时模式 " (schema on read) ,加载数据时不进行数据格式的校验,读取数据时如果不合法则显示 NULL 。这种模式的优点是加载数据迅速。读时模式 -> 读时检查数据 -> Hive ;好处:加载数据快;问题:数据显示 NULL。
(六)Hive数据结构
二、DDL&DML命令
(一)数据库操作
- Hive的默认数据库为default,如果不指定数据库,则默认使用default;
- Hive的数据库名、表名不区分大小写;
- 名字不能使用数字开头;
- 不能使用关键字,尽量不使用特殊符号。
1.创建数据库
(1)语法
CREATE DATABASE [IF NOT EXISTS] database_name
[COMMENT database_comment]
[LOCATION hdfs_path]
[WITH DBPROPERTIES (property_name=property_value, ...)];-- K-V键值对信息
(2)案例
1)创建一个数据库,不指定路径:
create database db_hive1;
注:若不指定路径,其默认路径为${/opt/soft/hive312/warehouse}/database_name.db
参考博文《Hive学习——单机版Hive的安装》2.2
2)创建一个数据库,指定路径:
create database db_hive2 location '/db_hive2';
3)创建一个数据库带有dbproperties
create database db_hive3 with dbproperties('create_date'='2023-01-01');
2.查看数据库
(1)展示所有数据库
SHOW DATABASES [LIKE 'identifier_with_wildcards'];
注:like通配表达式说明:*表示任意个任意字符,|表示或的关系。
-- 查看以'db'为开头的数据库
show databases like 'db*';
(2)查看数据库信息
DESCRIBE | DESC DATABASE [EXTENDED] db_name;
1)查看基本信息
desc database db_hive3;
2)查看更多信息
desc database extended db_hive3;
3.修改数据库
--修改dbproperties
ALTER DATABASE database_name SET DBPROPERTIES (property_name=property_value, ...);
--修改location
ALTER DATABASE database_name SET LOCATION hdfs_path;
--修改owner user
ALTER DATABASE database_name SET OWNER USER user_name;
注:修改数据库location,不会改变当前已有表的路径信息,而只是改变后续创建的新表的默认的父目录。
alter database db_hive3 set dbproperties ('create_date'='2023-02-01');
4.删除数据库
DROP DATABASE [IF EXISTS] database_name [RESTRICT|CASCADE];
注:RESTRICT:严格模式,若数据库不为空,则会删除失败,默认为该模式。
CASCADE:级联模式,若数据库不为空,则会将库中的表一并删除。
drop database db_hive1 restrict ;
drop database db_hive3 cascade ;
5.切换(使用)指定数据库
use database_name;
(二)表操作
1.建表语法
create [external] table [IF NOT EXISTS] table_name
[(colName colType [comment 'comment'], ...)]
[comment table_comment]
[partition by (colName colType [comment col_comment], ...)]
[clustered BY (colName, colName, ...)
[sorted by (col_name [ASC|DESC], ...)] into num_buckets
buckets]
[row format row_format]
[stored as file_format]
[LOCATION hdfs_path]
[TBLPROPERTIES (property_name=property_value, ...)]
[AS select_statement];
CREATE [TEMPORARY] [EXTERNAL] TABLE [IF NOT EXISTS]
[db_name.]table_name
LIKE existing_table_or_view_name
[LOCATION hdfs_path];
1. CREATE TABLE :按给定名称创建表,如果表已经存在则抛出异常。可使用 if notexists 规避;2. EXTERNAL 关键字:创建外部表,否则创建的是内部表( 管理表 ) ;删除内部表时,数据和表的定义(元数据)同时被删除;删除外部表时,仅仅删除了表的定义(元数据),数据保留;在生产环境中,多使用外部表;3. comment :表的注释;4. partition by :对表中数据进行分区,指定表的分区字段;5. clustered by :创建分桶表,指定分桶字段;6. sorted by :对桶中的一个或多个列排序,较少使用。
存储子句:
ROW FORMAT DELIMITED
[FIELDS TERMINATED BY char] -- 字段分隔符
[COLLECTION ITEMS TERMINATED BY char] -- 集合分隔符
[MAP KEYS TERMINATED BY char] -- map分隔符
[LINES TERMINATED BY char] | SERDE serde_name -- 行分隔符
[WITH SERDEPROPERTIES (property_name=property_value,
property_name=property_value, ...)]
AS :后面可以接查询语句,表示根据后面的查询结果创建表。LIKE : like 表名,允许用户复制现有的表结构,但是不复制数据。
查看建表语句:
show create table 表名;
2.内部表
-- 创建内部表
create table t1( id int, name string, hobby array<string>, addr map<string,string> )row format delimited fields terminated by ';' collection items terminated by ',' map keys terminated by ':' lines terminated by '\n';
-- 显示表的定义,显示的信息较少desc t1;
-- 显示表的定义,显示的信息多,格式友好
desc formatted t1;
-- 数据源2;zhangsan;book,TV,code;beijing:chaoyang,shagnhai:pudong 3;lishi;book,code;nanjing:jiangning,taiwan:taibei 4;wangwu;music,book;heilongjiang:haerbin
-- 加载数据
load data local inpath '/opt/stufile/t1.dat' into table t1;
-- 查询数据select * from t1;
-- 查询数据文件
dfs -cat /opt/soft/hive312/warehouse/mydb.db/t1/t1.dat; 2;zhangsan;book,TV,code;beijing:chaoyang,shagnhai:pudong 3;lishi;book,code;nanjing:jiangning,taiwan:taibei 4;wangwu;music,book;heilongjiang:haerbin
-- 删除表,表和数据同时被删除
drop table t1;
-- 再次查看数据文件,已经被删除
dfs -ls /opt/soft/hive312/warehouse/mydb.db
3.外部表
-- 创建外部表
create external table t2( id int, name string, hobby array<string>, addr map<string,string> )row format delimited fields terminated by ';' collection items terminated by ',' map keys terminated by ':' lines terminated by '\n' location '/opt/lsl';-- 指定外部表的存放目录,如果hdfs没有创建,会自动创建
-- 显示表的定义
desc formatted t2;
-- 加载数据
load data local inpath '/opt/stufile/t1.dat' [overwrite] into table t2;
-- 查询表数据
select * from t2;
-- 查看数据源
dfs -cat /opt/lsl/t1.dat;
-- 删除外部表,表不存在,但是数据还在
drop table t2; show tables ; dfs -cat /opt/lsl/t1.dat;
4.内部表与外部表的转换
(1)内部表转外部表
alter table t1 set tblproperties ('EXTERNAL'='TRUE');
(2)外部表转内部表
alter table t1 set tblproperties ('EXTERNAL'='FALSE');
小结
建表时:
- 如果不指定external关键字,创建的是内部表;
- 指定external关键字,创建的是外部表;
删表时:
- 删除外部表时,仅删除表的定义,表的数据不受影响;
- 删除内部表时,表的数据和定义同时被删除;
外部表的使用场景:
- 想保留数据时使用,生产多用外部表。
5.分区表
- Hive在执行查询时,一般会扫描整个表的数据。由于表的数据量大,全表扫描消耗时 间长、效率低。
- 而有时候,查询只需要扫描表中的一部分数据即可,Hive引入了分区表的概念,将表 的数据存储在不同的子目录中,每一个子目录对应一个分区。只查询部分分区数据时,可避免全表扫描,提高查询效率。
- 在实际中,通常根据时间、地区等信息进行分区。
-- 创建分区表
create table if not exists t3 ( id int, name string, hobby array<string>, addr map<string,string> ) partitioned by (dt string) row format delimited fields terminated by ';' collection items terminated by ',' map keys terminated by ':' lines terminated by '\n';
-- 加载数据到对应分区,该语句不需要新建分区
load data local inpath '/opt/stufile/t1.dat' into table t3 partition (dt = '2020-06-01'); load data local inpath '/opt/stufile/t1.dat' into table t3 partition (dt = '2020-06-02');
-- 查看分区
show partitions t3;
-- 新增分区不加载数据
alter table t3 add partition (dt = '2020-06-03');
-- 新增多个分区,不加载数据
alter table t3 add partition (dt = '2020-06-04') partition (dt = '2020-06-05');
-- 新增多个分区,准备数据
dfs -cp /opt/soft/hive312/warehouse/mydb.db/t3/dt=2020-06-01 /opt/soft/hive312/warehouse/mydb.db/t3/dt=2020-06-07; dfs -cp /opt/soft/hive312/warehouse/mydb.db/t3/dt=2020-06-01 /opt/soft/hive312/warehouse/mydb.db/t3/dt=2020-06-08;
-- 拷贝后检查是否有数据
dfs -cat /opt/soft/hive312/warehouse/mydb.db/t3/dt=2020-06-07/t1.dat; dfs -cat /opt/soft/hive312/warehouse/mydb.db/t3/dt=2020-06-08/t1.dat;
-- 新增多个分区,加载数据
alter table t3 add partition (dt = '2020-06-07') location '/opt/soft/hive312/warehouse/mydb.db/t3/dt=2020-06-07' partition (dt = '2020-06-08') location '/opt/soft/hive312/warehouse/mydb.db/t3/dt=2020-06-08';
-- 查询数据
select * from t3;
-- 修改分区的hdfs路径
alter table t3 partition (dt = '2020-06-01') set location '/opt/soft/hive312/warehouse/mydb.db/t3/dt=2020-06-03';
-- 加载数据
load data local inpath '/opt/stufile/t1.dat' into table t3 partition (dt = '2020-06-03');
-- 删除分区:可以删除一个或多个分区,用逗号隔开
alter table t3 drop partition (dt='2020-06-03'),partition (dt='2020-06-04');
6.分桶表
当单个的分区或者表的数据量过大,分区不能更细粒度的划分数据,就需要使用分桶技术将数据划分成更细的粒度。将数据按照指定的字段进行分成多个桶中去,即将数据按照字段进行划分,数据按照字段划分到多个文件当中去。分桶的原理:
- MR中:key.hashCode % reductTask
- Hive中:分桶字段.hashCode % 分桶个数
-- 创建分桶表
create table course( id int, name string, score int ) clustered by (id) into 3 buckets row format delimited fields terminated by '\t';
-- 创建普通表
create table course_common( id int, name string, score int ) row format delimited fields terminated by '\t';
-- 普通表加载数据
load data local inpath '/opt/stufile/course.dat' into table course_common; 1 java 90 1 c 78 1 python 91 1 hadoop 80 2 java 75 2 c 76 2 python 80 2 hadoop 93 3 java 98 3 c 74 3 python 89 3 hadoop 91 5 java 93 6 c 76 7 python 87 8 hadoop 88
注:数据之间不是空格,而是Tab键
-- 通过 insert ... select ... 给桶表加载数据
insert into table course select * from course_common;
-- 查看分桶表
dfs -ls /opt/soft/hive312/warehouse/mydb.db/course;
-- 第一个分区:id%3=0
dfs -cat /opt/soft/hive312/warehouse/mydb.db/course/000000_0;
-- 第二个分区:id%3=1
dfs -cat /opt/soft/hive312/warehouse/mydb.db/course/000001_0;
-- 第三个分区:id%3=2
dfs -cat /opt/soft/hive312/warehouse/mydb.db/course/000002_0;
备注:分桶规则: 分桶字段.hashCode % 分桶数分桶表加载数据时,使用 insert... select ... 方式进行网上有资料说要使用分区表需要设置 hive.enforce.bucketing=true ,是 Hive1.x 以前的版本; Hive 2.x 中,删除了该参数,始终可以分桶;
7.修改表与删除表
--修改表名
alter table course_common rename to course_common1;
-- 修改列名alter table course_common1 change column id cid int;
-- 修改字段类型
alter table course_common1 change column cid cid string;
注:修改字段数据类型时,要满足数据类型转换的要求。如 int 可以转为 string ,但是string 不能转为 int。-- 增加字段,默认数据为nullalter table course_common1 add columns (common string);
-- 删除字段
alter table course_common1 replace columns (id string,cname string,score int);
注:这里仅仅只是在元数据中删除了字段,并没有改动hdfs上的数据文件
-- 删除表drop table course_common1;
(三)数据操作
1.数据导入
LOAD DATA [LOCAL] INPATH 'filepath' [OVERWRITE] INTO TABLE tablename [PARTITION (partcol1=val1, partcol2=val2 ...)]
LOCAL :LOAD DATA LOCAL ... 从本地文件系统加载数据到Hive表中,本地文件会拷贝到Hive表指定的位置;LOAD DATA ... 从HDFS加载数据到Hive表中,HDFS文件移动到Hive表指定的位置INPATH :加载数据的路径OVERWRITE :覆盖表中已有数据;否则表示追加数据PARTITION :将数据加载到指定的分区-- 创建表
CREATE TABLE tabA ( id int, name string, area string ) ROW FORMAT DELIMITED FIELDS TERMINATED BY ',';
-- 加载本地文件到hive(tabA),本地文件会拷贝到表中
load data local inpath '/opt/stufile/sourceA.txt' into table tabA; 1,fish1,SZ 2,fish2,SH 3,fish3,HZ 4,fish4,QD 5,fish5,SR
-- 查看tabA数据
select * from tabA;
-- 本地文件还在
-- 加载hdfs文件到hive(tabA),本地文件会移动到表中
-- 检查hdfs文件,已经被转移load data inpath '/data/sourceA.txt' into table tabA;
dfs -cat /data/sourceA.txt;
-- 加载数据覆盖表中已有数据
load data local inpath '/opt/stufile/sourceA.txt' overwrite into table tabA;
-- 创建表时加载数据dfs -mkdir /data/tabB; dfs -put /opt/stufile/sourceA.txt /data/tabB; dfs -cat /data/tabB/sourceA.txt; create table tabB ( id int, name string, area string ) row format delimited fields terminated by ',' location '/data/tabB'; select * from tabB;
2.插入数据
-- 创建分区表
create table tabC( id int, name string, area string )partitioned by (month string) row format delimited fields terminated by ',';
-- 插入数据
insert into tabC partition (month = '202301') values (1, 'zhangsan', 'BJ'), (2, 'lisi', 'SH'), (3, 'wangwu', 'NJ');
-- 结果
-- 插入查询的结果数据
insert into tabC partition (month = '202302') select id, name, area from tabC where month = '202301';
-- 结果
-- 多表(多分区)插入模式
from tabC insert overwrite table tabC partition (month = '202303') select id, name, area where month = '202302' insert overwrite table tabC partition (month = '202304') select id, name, area where month = '202302';
-- 结果
-- 创建表并插入数据(as select)
insert overwrite local directory '/opt/stufile/tabC' select * from tabC where month='202304';
-- 结果
[root@lxm147 ~]# cat /opt/stufile/tabC/000000_0 1zhangsanBJ202304 2lisiSH202304 3wangwuNJ202304
-- 将查询结果格式化输出到本地
insert overwrite local directory '/opt/stufile/tabC2' row format delimited fields terminated by ' ' select * from tabC;
-- 结果
[root@lxm147 ~]# cat /opt/stufile/tabC2/000000_0 1 zhangsan BJ 202301 2 lisi SH 202301 3 wangwu NJ 202301 1 zhangsan BJ 202302 2 lisi SH 202302 3 wangwu NJ 202302 1 zhangsan BJ 202303 2 lisi SH 202303 3 wangwu NJ 202303 1 zhangsan BJ 202304 2 lisi SH 202304 3 wangwu NJ 202304
3.数据导出
-- 将查询结果导出到hdfs
insert overwrite directory '/data/tabC3' row format delimited fields terminated by ' ' select * from tabC;
-- 结果
dfs -cat /data/tabC3/000000_0;
-- dfs 命令导出数据到本地。本质是执行数据文件的拷贝
dfs -get /data/tabC3/000000_0 /opt/stufile/tabC4; [root@lxm147 ~]# cat /opt/stufile/tabC4 1 zhangsan BJ 202301 2 lisi SH 202301 3 wangwu NJ 202301 1 zhangsan BJ 202302 2 lisi SH 202302 3 wangwu NJ 202302 1 zhangsan BJ 202303 2 lisi SH 202303 3 wangwu NJ 202303 1 zhangsan BJ 202304 2 lisi SH 202304 3 wangwu NJ 202304
-- hive 命令导出数据到本地。执行查询将查询结果重定向到文件
[root@lxm147 ~]# hive -e "select * from mydb.tabC" > /opt/stufile/a.log; [root@lxm147 ~]# cat /opt/stufile/a.log tabc.id tabc.name tabc.area tabc.month 1 zhangsan BJ 202301 2 lisi SH 202301 3 wangwu NJ 202301 1 zhangsan BJ 202302 2 lisi SH 202302 3 wangwu NJ 202302 1 zhangsan BJ 202303 2 lisi SH 202303 3 wangwu NJ 202303 1 zhangsan BJ 202304 2 lisi SH 202304 3 wangwu NJ 202304
-- export 导出数据到HDFS。使用export导出数据时,不仅有数还有表的元数据信息
export table tabC to '/data/tabC4'; dfs -ls /data/tabC4;
-- export 导出的数据,可以使用 import 命令导入到 Hive 表中-- 使用 like tname 创建的表结构与原表一致。 create ... as select ...结构可能不一致create table tabE like tabc; import table tabE from '/user/hadoop/data/tabC4';
-- 截断表,清空表中的数据(注意:仅能操作内部表)
truncate table tabB;
小结:数据导入: load data / insert / create table .... as select ..... / import table数据导出: insert overwrite ... diretory ... / hdfs dfs -get / hive -e "select ..." > a.log / export table ...Hive 的数据导入与导出还可以使用其他工具: Sqoop 、 DataX 等;