一、数据库操作
1、创建数据库
语法格式:
CREATE (DATABASE|SCHEMA) [IF NOT EXISTS] database_name
[COMMENT database_comment]
[LOCATION hdfs_path]
[MANAGEDLOCATION hdfs_path]
[WITH DBPROPERTIES (property_name=property_value, ...)];
hive> create database r_db;
> 创建数据库时指定存储目录
hive> create database r_db1 location "/user/test";
> 创建数据库是指定描述信息
hive (default)> create database r_db2 comment "this is a test database";
> 显示数据库的信息
hive (default)> desc database r_db2;
或者
hive (default)> desc database extended r_db2;
> 创建时指定数据库的描述信息
hive (default)> create database r_db3 with dbproperties('author'='yjt','create'='2020-06-29');
hive (default)> desc database extended r_db3;
db_name comment location owner_name owner_type parameters
r_db3 hdfs://yjt:9000/hive/warehouse/r_db3.db hduser USER {create=2020-06-29, author=yjt}
> 对已经存在的数据库添加描述信息
hive (default)> alter database r_db3 set dbproperties("address"='beijin'); # 目前还不能删除属性,只能设置为''字符串
hive (default)> desc database extended r_db3;
db_name comment location owner_name owner_type parameters
r_db3 hdfs://yjt:9000/hive/warehouse/r_db3.db hduser USER {create=2020-06-29, address=beijin, author=yjt}
2、显示数据库
> 使用like 匹配
hive (default)> show databases like "shang.*";
OK
database_name
shanghai
3、删除数据库
hive (r_db2)> drop database r_db3;
FAILED: Execution Error, return code 1 from org.apache.hadoop.hive.ql.exec.DDLTask. InvalidOperationException(message:Database r_db3 is not empty. One or more tables exist.)
> 使用cascade强制删除
hive (r_db2)> drop database r_db3 cascade;
OK
其他的关于数据库的操作,查看官网
官网
二、表操作
语法格式
CREATE [TEMPORARY] [EXTERNAL] TABLE [IF NOT EXISTS] [db_name.]table_name -- (Note: TEMPORARY available in Hive 0.14.0 and later)
[(col_name data_type [column_constraint_specification] [COMMENT col_comment], ... [constraint_specification])]
[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]
[SKEWED BY (col_name, col_name, ...) -- (Note: Available in Hive 0.10.0 and later)]
ON ((col_value, col_value, ...), (col_value, col_value, ...), ...)
[STORED AS DIRECTORIES]
[
[ROW FORMAT row_format]
[STORED AS file_format]
| STORED BY 'storage.handler.class.name' [WITH SERDEPROPERTIES (...)] -- (Note: Available in Hive 0.6.0 and later)
]
[LOCATION hdfs_path]
[TBLPROPERTIES (property_name=property_value, ...)] -- (Note: Available in Hive 0.6.0 and later)
[AS select_statement]; -- (Note: Available in Hive 0.5.0 and later; not supported for external tables)
管理表
1、创建表
create table test1(
id int,
name string,
subo array<string>,
deb map<string, float>,
address struct<city:string,state:string>)
row format delimited
fields terminated by ','
collection items terminated by '_'
map keys terminated by ':'
lines terminated by "
"
location "/hive/warehouse/r_db2.db/test1"
tblproperties('create_time'='2020-06-29');
2、加载数据
hive (default)> load data local inpath "/tmp/hive/hive.txt" into table test1;
测试数据:
[hduser@yjt hive]$ cat hive.txt
1,yjt,n1_n2,key1:12.0,beijin_changping
2,yjl,n3_n4,key2:23.11,chongqin_yubei
3、查询
hive (default)> select * from test1;
OK
test1.id test1.name test1.subo test1.deb test1.address
1 yjt ["n1","n2"] {"key1":12.0} {"city":"beijin","state":"changping"}
2 yjl ["n3","n4"] {"key2":23.11} {"city":"chongqin","state":"yubei"}
Time taken: 0.215 seconds, Fetched: 2 row(s)
查询指定的数据
hive (default)> select subo[0], deb['key1'], address.city from test1 where name='yjt';
OK
_c0 _c1 city
n1 12.0 beijin
Time taken: 0.319 seconds, Fetched: 1 row(s)
4、复制表结构
hive (default)> create table test2 like test1;
OK
Time taken: 0.21 seconds
hive (default)> show create table test2;
OK
createtab_stmt
CREATE TABLE `test2`(
`id` int,
`name` string,
`subo` array<string>,
`deb` map<string,float>,
`address` struct<city:string,state:string>)
ROW FORMAT SERDE
'org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe'
WITH SERDEPROPERTIES (
'collection.delim'='_',
'field.delim'=',',
'line.delim'='
',
'mapkey.delim'=':',
'serialization.format'=',')
STORED AS INPUTFORMAT
'org.apache.hadoop.mapred.TextInputFormat'
OUTPUTFORMAT
'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat'
LOCATION
'hdfs://yjt:9000/hive/warehouse/test2'
TBLPROPERTIES (
'transient_lastDdlTime'='1593478235')
4、查看表的详细信息
hive (r_db2)> desc formatted test; # 输出结果易读性更强
hive (r_db2)> desc extended test;
5、删除表
hive (r_db2)> drop table test; #管理表在删除的时候不仅删除元数据,同时也删除hdfs上面存在的真实数据
外部表
1、拷贝数据到hdfs
> 数据样式
[hduser@yjt hive]$ cat test.txt
1,hadoop
2,spark
3,hive
4,hbase
5,python
> copy到hdfs
$ hadoop fs -put test.txt /user/hduser/test
2、创建外部表
hive (r_db2)> create external table test1(id int, name string) row format delimited fields terminated by ',' location "/user/hduser/test";
3、查看数据
hive (r_db2)> select * from test1;
OK
test1.id test1.name
1 hadoop
2 spark
3 hive
4 hbase
5 python
4、删除外部表
hive (r_db2)> drop table test1;
5、查看数据是否存在
hive (r_db2)> dfs -ls /user/hduser/test/;
Found 1 items
-rw-r--r-- 1 hduser supergroup 41 2020-06-30 10:32 /user/hduser/test/test.txt
管理表与分区表之间的转换
1、首先创建管理表
hive (r_db2)> create table manag_table(id int);
hive (r_db2)> desc formatted manag_table;
Table Type: MANAGED_TABLE
2、管理表转外部表
hive (r_db2)> alter table manag_table set tblproperties ('EXTERNAL'='TRUE');
hive (r_db2)> desc formatted manag_table;
Table Type: EXTERNAL_TABLE
3、外部表转管理表
把刚才转换成的外部表manag_table重新转化为内部表
hive (r_db2)> alter table manag_table set tblproperties ('EXTERNAL'='FALSE');
注意: 'EXTERNAL'='FALSE' 和 'EXTERNAL'='TRUE' 是固定写法,区分大小写,如果写错,仅仅当做表属性被显示
分区表
数据分区主要是用于高效的查询和分散压力,hive里面的分区表也是这样,对数据分区,当查询的时候只查询某个条件的时候,不用进行全表扫描。
hive分区表:所谓的分区表就是在hdfs目录上面对当前进行分区的字段创建一个目录(分层存储),同时进行分区的字段不能在源字段内。
分区管理表
1、创建分区管理表
hive (r_db2)> create table test3(id int, name string) partitioned by(currentDate string) row format delimited fields terminated by ',';
2、添加静态分区
hive (r_db2)> alter table test3 add partition(currentDate="2020-06-30"); # 这一步可以省略,只是为了说明可以通过alter的方式创建分区,需要注意这里的关键字是partition,创建表的时候关键字是partitioned(多了ed);当然也支持创建多个分区,但是创建分区的时候需要以空格分离
> 创建多分区
hive (r_db2)> alter table test3 add partition(currentDate="2020-07-04") partition(currentDate="2020-07-05");
hive (r_db2)> alter table test3 add partition(currentDate="2020-07-02", currentDate="2020-07-03"); # **这种是错误的**
3、加载数据
hive (r_db2)> load data local inpath '/tmp/hive/hive1.txt' overwrite into table test3 partition(currentDate="2020-06-30");
4、查询
hive (r_db2)> select * from test3;
OK
test3.id test3.name test3.currentdate
1 hadoop 2020-06-30
2 spark 2020-06-30
1 hadoop 2020-07-01
2 spark 2020-07-01
Time taken: 0.2 seconds, Fetched: 4 row(s)
hive (r_db2)> select * from test3 where currentdate="2020-07-01"; # 指定分区查询
OK
test3.id test3.name test3.currentdate
1 hadoop 2020-07-01
2 spark 2020-07-01
> 联合查询
hive (r_db2)> select * from test3 where currentdate="2020-06-30" union select * from test3 where currentdate="2020-07-01";
5、删除分区
> 显示当前的分区数
hive (r_db2)> show partitions test3;
OK
partition
currentdate=2020-06-30
currentdate=2020-07-01
currentdate=2020-07-03
currentdate=2020-07-04
currentdate=2020-07-05
currentdate=2020-07-06
> 删除分区
hive (r_db2)> alter table test3 drop partition(currentDate="2020-07-06"); # 删除单个分区
Dropped the partition currentdate=2020-07-06
OK
Time taken: 0.315 seconds
hive (r_db2)> alter table test3 drop partition(currentDate="2020-07-04"),partition(currentDate="2020-07-05"); # 删除多个分区,注意:多分区之间是逗号,与刚刚的添加分区用空格分开是不同的。
Dropped the partition currentdate=2020-07-04
Dropped the partition currentdate=2020-07-05
OK
6、让分区表与数据产生关联的三种方式
hive当中查询数据的时候首先会从元数据里面查询对应的信息(比如实际存放数据的路径),然后去读取数据,同理让分区表与数据产生关联,就是修改元数据的对应关系,让表可以关联到最终存放在hdfs上的数据。
方式1:
① 直接在hdfs创建分区目录
hive (r_db2)> dfs -mkdir /hive/warehouse/r_db2.db/test3/currentdate=2020-07-04;
② 拷贝数据
hive (r_db2)> dfs -put /tmp/hive/hive2.txt /hive/warehouse/r_db2.db/test3/currentdate=2020-07-04;
③ 直接查询
hive (r_db2)> select * from test3 where currentdate="2020-07-04"; #可以看到是没有数据的,说明元数据与真实数据还没有对应上
OK
test3.id test3.name test3.currentdate
Time taken: 0.252 seconds
④ 修复表
hive (r_db2)> msck repair table test3;
OK
Partitions not in metastore: test3:currentdate=2020-07-04
Repair: Added partition to metastore test3:currentdate=2020-07-04
Time taken: 0.262 seconds, Fetched: 2 row(s)
hive (r_db2)> select * from test3 where currentdate="2020-07-04";
OK
test3.id test3.name test3.currentdate
100 yjt 2020-07-04
200 yjl 2020-07-04
Time taken: 0.254 seconds, Fetched: 2 row(s)
方式2:
接上一步方式1,在put数据到hdfs后,不使用msck修复,而是使用alter ... add 添加分区的方式,修改元数据
方式3:
接方式1,创建完分区目录以后,直接load数据到分区表,同时指定创建的分区目录。
7、查看某个表的特定分区
hive (r_db2)> show partitions test3 partition(currentdate="2020-06-30");
8、动态分区
#开启动态分区功能
set hive.exec.dynamic.partition=true;
# 动态分区模式,默认是strict
set hive.exec.dynamic.partition.mode=nonstrict; #如果是strict,在使用创建动态分区的时候需要先指定一个静态分区,同时静态分区在动态分区前面。
hive (r_db2)> create table test5(id int, name string) partitioned by(score string); #创建测试表(源表)
hive (r_db2)> create table test6 like test5;
hive (r_db2)> load data local inpath "/tmp/hive/hive2.txt" into table test5 partition(score='60'); #加载数据到源表,同时指定分区
hive (r_db2)> insert into test6 partition(score) select s.id,s.name, s.score from test5 as s; # 使用动态分区的方式插入数据到表test6,
或者
hive (r_db2)> insert into test6 select s.id,s.name, s.score from test5 as s; # 测试了一下这种方式也可以,同时不需要指定动态分区为严格。
分区外部表
1、创建分区外部表
hive (r_db2)> create external table test4(id int, name string) partitioned by(testPartion string) row format delimited fields terminated by ',';
2、添加分区和指定存储位置
hive (r_db2)> alter table test4 add partition(testPartion="2020-06-30") location "/out1/2020-06-30";
3、创建目分区录
hive (r_db2)> dfs -mkdir /out1/2020-06-30;
4、put数据
hive (r_db2)> dfs -put "/tmp/hive/hive2.txt" "/out1/2020-06-30";
5、查询
hive (r_db2)> select * from test4 where testPartion="2020-06-30";
OK
test4.id test4.name test4.testpartion
100 yjt 2020-06-30
200 yjl 2020-06-30
6、查看分区的位置
hive (r_db2)> desc formatted test4 partition(testPartion="2020-06-30");