建表语句
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]
[stored as file_format]
[location hdfs_path]
解释
字段 | 说明 |
---|---|
EXTERNAL | 关键字可以让用户创建一个外部表,在建表的同时指定一个指向实际数据的路径( LOCATION) |
LIKE | 允许用户复制现有的表结构,但是不复制数据 |
ROW FORMAT DELIMITED | 指定分割符,默认是“\001” |
PARTITIONED BY | 指定分区,一个表可以拥有一个或者多个分区,每个分区以文件夹的形式单独存在表文件夹的目录下。 |
stored as sequencefile\textfile\rcfile | 如果文件数据是纯文本,可以使用 STORED AS TEXTFILE。如果数据需要压缩。 |
CLUSTERED BY INTO num_buckets BUCKETS | 分桶,Hive 采用对列值哈希,然后除以桶的个数求余的方式决定该条记录存放在哪个桶当中,在hdfs表现为文件 |
ROW FORMAT DELIMITED(指定分隔符):
-
[fields terminated by char]:指定字段之间的分隔符默认是“\001”
-
collection items terminated by char:指定集合的分隔符
如:``` 数据: zhangsan beijing,shanghai,tianjin,hangzhou 建表语句: create table complex_array(name string,work_locations array<string>) ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t' COLLECTION ITEMS TERMINATED BY ','; 结果: +---------------------+----------------------------------------------+--+ | complex_array.name | complex_array.work_locations | +---------------------+----------------------------------------------+--+ | zhangsan | ["beijing","shanghai","tianjin","hangzhou"] | +---------------------+----------------------------------------------+--+ ```
-
map keys terminated by char:指定map集合的分割符
如:
数据: 1,zhangsan,唱歌:非常喜欢-跳舞:喜欢-游泳:一般般 建表语句: create table t_map(id int,name string,hobby map<string,string>) row format delimited fields terminated by ',' collection items terminated by '-' map keys terminated by ':' ; 结果: 1 | zhangsan | {"唱歌":"非常喜欢","跳舞":"喜欢","游泳":"一般般"} |
-
with serdeproperties:自定义分割,序列化和反序列化,serde序列化和反序列化
如:
数据: id=123,name=steven 建表语句:使用正则 create table test1(id int, name string) row format serde 'org.apache.hadoop.hive.serde2.RegexSerDe' with serdeproperties ("input.regex" = "id=(.*),name=(.*)") stored as textfile; 结果: 123 steven
创建数据库
create database if not exists dbbank;
删除数据库
drop database if exists itcast cascade;
注意:1. 默认情况不允许删除有表的数据,添加cascade可以删除
2.删除的话/hive/warehouse下的数据也会删除,元数据也会删除。
hive建表语句
1、查看内部表还是外部表:
desc formatted tablename
结果:
Table Type: MANAGED_TABLE 表示内部表
Table Type: EXTERNAL_TABLE 表示外部表
2、 外部表和内部表:
建表
- 创建外部表 (external):
第一种
create external table if not exists tb01(name string,age int,male varchar(2))row format delimited fields terminated by ",";
创建表时就加载数据: (使用location指定路径)
create external table if not exists tb01(name string,age int,male varchar(2))row format delimited fields terminated by "," location '/user/root/hivedata';
- . 显示命令:
show tables;
显示当前数据库所有表
show databases |schemas;
显示所有数据库
show partitions table_name;
显示表分区信息,不是分区表执行报错
show functions;
显示当前版本 hive 支持的所有方法
desc extended table_name;
查看表信息
desc formatted table_name;
查看表信息(格式化美观)
describe database database_name;
查看数据库相关信息
- 创建外部表:
第一种
create table if not exists tb01(name string comment '名字',age int comment '年龄',male varchar(2) comment '性别' )row format delimited fields terminated by ",";
第二种
create table if not exists tb02(name string comment '名字',age int comment '年龄',male varchar(2) comment '性别' )row format delimited fields terminated by "," location '/user/root/hivedata';
注意:
- 中文乱码,可以修改元数据表
alter table COLUMNS_V2 modify COMMENT varchar(256) character set utf8;
- 外部表删除数据不会删除hdfs的数据,内部表会
- 外部表不会删除hdfs的数据,如果下次创建的表与tb01名字相同,因为在warehouse目录下,则会自动将数据加载进去
DML 操作
1. load加载数据:
加载hdfs上的数据:
load data inpath '/user/root/student.txt' into table tb01;
加载本地数据(本地数据必须在hive的服务端):
load data local inpath '/user/root/student.txt' into table tb01;
注意:
这种会把数据移动到hive/warehouse目录下
2. location加载数据:
create table if not exists tb02(name string comment '名字',age int comment '年龄',male varchar(2) comment '性别' )row format delimited fields terminated by "," location '/user/root/hivedata';
注意:
这种方式不会移动数据的目录
3. Insert:
insert overwrite table stu
select * from student ;
hive的分桶和分区
分区:
在hdfs上表现是一个文件夹
查看表的分区:
show partitions person_d_p
动态分区:
- 导入数据时可以根据字段映射到对应的分区
- 每一个分区至少有一条数据
- 如果数据量很大,每条插入语句都要指定键值很麻烦,于是就有了动态分区
- 动态分区比静态分区的方式消耗性能,默认严格下动态分区至少有一个静态分区。
et hive.exec.dynamic.partition=true; #是否开启动态分区功能,默认false关闭。
set hive.exec.dynamic.partition.mode=nonstrict; #动态分区的模式,默认strict,表示插入时必须指定至少一个分区为静态分区,nonstrict模式表示允许所有的分区字段都可以使用动态分区。
insert overwrite table d_p_t partition (month,day)
select ip,substr(day,1,7) as month,day from tablename;
静态分区:
-
静态分区在插入数据时需要指定分区键值,好让数据插入指定分区中
-
有可能存在某一个分区中一条数据都没有
insert into part_person PARTITION(date='2016-11-11') values('2','ss1');
insert into part_person PARTITION(date='2016-11-13') values('3','ss2');
分桶:
根据指定的列的hash值,分到不同的文件,方便join减少笛卡尔积
CREATE TABLE IF NOT EXISTS person_bkt
(
id int,
name string,
country string,
dt string
)
CLUSTERED BY(country) SORTED BY (id) INTO 4 BUCKETS;
set hive.enforce.bucketing=true
- 分桶查询
select * from person_bkt cluster by (country) - 分桶查询抽样
select * from person_bkt tablesample (bucket 2 out of 4 on id);
注意:2代表从第几个桶开始,4代表取多少个桶,必须是桶总数的倍数,可以使用desc - order by全局排序,sort by保证每个reduce task有序;