熟悉了Hive的库操作后,本文来介绍Hive中的的建表、删表操作。
Hive建表的全部建表语法如下:
CREATE [EXTERNAL] TABLE [IF NOT EXISTS] 表名
(列名 data_type [COMMENT 列注释], ...)
[COMMENT 表注释]
[PARTITIONED BY (列名 data_type [COMMENT 列注释], ...)]
[CLUSTERED BY (列名, 列名, ...)
[SORTED ,BY (列名 [ASC|DESC], ...)] INTO num_buckets BUCKETS]
[ROW FORMAT row_format]
[STORED AS file_format]
[LOCATION hdfs_path]
所有[ ]中的内容都是可选项,即可有可无,下面我们分别详细介绍。
其中
CREATE [EXTERNAL] TABLE [IF NOT EXISTS] 表名
(列名 data_type)
是建表语句必须有的,举个栗子,这是后续实战篇要用到的第一个表,用户启动表:
CREATE TABLE t_od_use_cnt (
date_8 INT
,platform string
,app_version string
,user_id BIGINT
,use_cnt INT
,is_active TINYINT
);
首先我们建一个库app,然后使用并在其中建表,执行效果如下:
hive> create database app;
OK
Time taken: 0.899 seconds
hive> use app;
OK
Time taken: 0.03 seconds
hive> create table t_od_use_cnt(
> date_8 int
> ,platform string
> ,app_version string
> ,user_id bigint
> ,use_cnt int
> ,is_active tinyint
> );
OK
Time taken: 0.389 seconds
hive>
ps:Hive中的关键字大小写是不区分的,所有关键字均可使用小写。
DESC 表名;
查询上一步新建表的字段及字段对应的数据类型,运行效果如下:
hive> desc t_od_use_cnt;
OK
date_8 int
platform string
app_version string
user_id bigint
use_cnt int
is_active tinyint
Time taken: 0.28 seconds, Fetched: 6 row(s)
hive>
删除表的语句和删除库的类似,只是把database换成了table,都是使用drop关键字进行删除操作。
DROP TABLE 表名;
这里我们先删去刚才新建的表t_od_use_cnt,重新建一个有字段注释的表,因为Hive中是不允许有同名表存在的。
使用刚学的删表语句:
DROP TABLE t_od_use_cnt;
执行效果如下:
hive> drop table t_od_use_cnt;
OK
Time taken: 0.898 seconds
hive>
重新建表,为字段添加中文注释,注意需要Xshell编码格式已修改为UTF-8。
CREATE TABLE t_od_use_cnt (
date_8 INT comment '日期'
,platform string comment '平台 android,ios'
,app_version string comment 'app版本'
,user_id BIGINT comment '用户id'
,use_cnt INT comment '当日使用次数'
,is_active TINYINT comment '是否活跃'
);
查询上一步新建的表,执行效果如下:
hive> desc t_od_use_cnt;
OK
date_8 int ??
platform string ?? android?ios
app_version string APP??
user_id bigint ??id
use_cnt int ??????
is_active tinyint ????
Time taken: 0.28 seconds, Fetched: 6 row(s)
hive>
此时字段注释里的中文显示是乱码,英文可以正常显示,在工作中这种情况我们是不会遇到的,运维的同事会帮我们搞定,如果是使用我提供的虚拟机的同学,此时会遇到这种情况,按如下操作即可:
[root@hadoop ~]# mysql -uroot -proot
Warning: Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 122
Server version: 5.6.25-log MySQL Community Server (GPL)
Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql>
use hive;
alter table COLUMNS_V2 modify column comment varchar(256) character set utf8;
alter table TABLE_PARAMS modify column PARAM_VALUE varchar(4000) character set utf8;
alter table PARTITION_KEYS modify column PKEY_COMMENT varchar(4000) character set utf8;
alter table PARTITION_PARAMS modify column PARAM_VALUE varchar(4000) character set utf8;
运行效果如下:
mysql> use hive;
Database changed
mysql> alter table COLUMNS_V2 modify column comment varchar(256) character set utf8;
Query OK, 25 rows affected (0.75 sec)
Records: 25 Duplicates: 0 Warnings: 0
mysql> alter table TABLE_PARAMS modify column PARAM_VALUE varchar(4000) character set utf8;
Query OK, 7 rows affected (0.28 sec)
Records: 7 Duplicates: 0 Warnings: 0
mysql> alter table PARTITION_KEYS modify column PKEY_COMMENT varchar(4000) character set utf8;
Query OK, 0 rows affected (0.32 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> alter table PARTITION_PARAMS modify column PARAM_VALUE varchar(4000) character set utf8;
Query OK, 0 rows affected (0.16 sec)
Records: 0 Duplicates: 0 Warnings: 0
hive> drop table t_od_use_cnt;
OK
Time taken: 0.456 seconds
hive> CREATE TABLE t_od_use_cnt(
> date_8 INT COMMENT '日期'
> ,platform STRING COMMENT '平台 android,ios'
> ,app_version STRING COMMENT 'APP版本'
> ,user_id BIGINT COMMENT '用户id'
> ,use_cnt INT COMMENT '当日使用次数'
> ,is_active TINYINT COMMENT '是否活跃'
> );
OK
Time taken: 0.106 seconds
hive> desc t_od_use_cnt;
OK
date_8 int 日期
platform string 平台 android,ios
app_version string APP版本
user_id bigint 用户id
use_cnt int 当日使用次数
is_active tinyint 是否活跃
Time taken: 0.115 seconds, Fetched: 6 row(s)
hive>
如果用户增加上可选项 IF NOT EXITS,那么若表已经存在了,Hive就会忽略掉后面的执行语句,而且不会有任何提示。在那些第一次执行时需要创建表的脚本中,这么写是非常有用的。不过工作中基本用不到,可以忽略。
在Hive中,我们把在建表时建表语句中没有加 [EXTERNAL]的表称为内部表或者管理表,代表着Hive可以控制这个表的生命周期,如果drop掉这个表,那么这个表的元数据和数据会被一起删掉。默认情况下,Hive会给数据指定一个默认的HDFS中的存储目录,上面的表所在的目录是hdfs://hadoop:9000/usr/hive/warehouse/app.db/t_od_use_cnt,/usr/hive/warehouse是默认的数据仓库路径地址,app.db是数据库目录,t_od_use_cnt是表目录。
通过以下语句可以查询到目录信息及很多其他表的信息,后续我们会经常用到这个语句:
DESC formatted 表名;
运行效果如下:
hive> desc formatted t_od_use_cnt;
OK
# col_name data_type comment
date_8 int 日期
platform string 平台 android,ios
app_version string app版本
user_id bigint 用户id
use_cnt int 当日使用次数
is_active tinyint 是否活跃
# Detailed Table Information
Database: app
Owner: root
CreateTime: Thu Apr 18 17:29:21 CST 2019
LastAccessTime: UNKNOWN
Protect Mode: None
Retention: 0
Location: hdfs://hadoop:9000/usr/hive/warehouse/app.db/t_od_use_cnt
Table Type: MANAGED_TABLE
Table Parameters:
transient_lastDdlTime 1555579761
# Storage Information
SerDe Library: org.apache.hadoop.hive.serde2.lazy.LazySimpleSerD
InputFormat: org.apache.hadoop.mapred.TextInputFormat
OutputFormat: org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat
Compressed: No
Num Buckets: -1
Bucket Columns: []
Sort Columns: []
Storage Desc Params:
serialization.format 1
Time taken: 0.157 seconds, Fetched: 31 row(s)
hive>
可以看到内部表的Table Type: MANAGED_TABLE
在Hive中,我们把在建表时建表语句中加 [EXTERNAL]的表称为外部表,与内部表不同,Hive只能拥有外部表的元数据(描述表的信息),删除表时并不会删掉数据本身,同时通过[LOCATION] 关键字自定义数据路径。
不过建外部表的操作在数据分析师的工作中基本用不到。建表语句如下:
CREATE EXTERNAL TABLE t_od_use_cnt (
date_8 INT comment '日期'
,platform string comment '平台 android,ios'
,app_version string comment 'app版本'
,user_id BIGINT comment '用户id'
,use_cnt INT comment '当日使用次数'
,is_active TINYINT comment '是否活跃'
) location '/data/test';
建表后使用 desc formatted t_od_use_cnt; 查询表信息如下:
hive> create database test;
OK
Time taken: 0.144 seconds
hive> use test;
OK
Time taken: 0.027 seconds
hive> create external table t_od_use_cnt(
> date_8 int comment '日期'
> ,platform string comment '平台 android,ios'
> ,app_version string comment 'app版本'
> ,user_id bigint comment '用户id'
> ,use_cnt int comment '当日使用次数'
> ,is_active tinyint comment '是否活跃'
> )
> location '/data/test';
OK
Time taken: 0.187 seconds
hive> desc formatted t_od_use_cnt;
OK
# col_name data_type comment
date_8 int 日期
platform string 平台 android,ios
app_version string app版本
user_id bigint 用户id
use_cnt int 当日使用次数
is_active tinyint 是否活跃
# Detailed Table Information
Database: test
Owner: root
CreateTime: Fri Apr 19 07:37:34 CST 2019
LastAccessTime: UNKNOWN
Protect Mode: None
Retention: 0
Location: hdfs://hadoop:9000/data/test
Table Type: EXTERNAL_TABLE
Table Parameters:
EXTERNAL TRUE
transient_lastDdlTime 1555630654
# Storage Information
SerDe Library: org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe
InputFormat: org.apache.hadoop.mapred.TextInputFormat
OutputFormat: org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat
Compressed: No
Num Buckets: -1
Bucket Columns: []
Sort Columns: []
Storage Desc Params:
serialization.format 1
Time taken: 0.134 seconds, Fetched: 32 row(s)
hive>
可以看到外部表的Table Type: EXTERNAL_TABLE
Hive中有分区表的概念,分区表改变了Hive对数据存储的组织方式,提高了查询速度。上面我们已经介绍过,如果我们在app数据库中建表,数据存储路径是hdfs://hadoop:9000/usr/hive/warehouse/app.db/t_od_use_cnt,如果我们以日期date_8作为分区字段,那么数据存储路径会反映出分区结构的子目录,例如:
/usr/hive/warehouse/app.db/t_od_use_cnt/date_8=20190401
/usr/hive/warehouse/app.db/t_od_use_cnt/date_8=20190402
/usr/hive/warehouse/app.db/t_od_use_cnt/date_8=20190403
/usr/hive/warehouse/app.db/t_od_use_cnt/date_8=20190404
/usr/hive/warehouse/app.db/t_od_use_cnt/date_8=20190405
......
这样查询时如果我们限定了分区范围,Hive就可以直接去相应的目录下查询数据,而不需要扫描整个表,所以当数据量很大时可以显著提高查询性能。
建立分区表要使用关键字[PARTITIONED BY (col_name data_type [COMMENT col_comment], ...)] ,注意分区的字段不可在普通字段中重复出现。分区表在工作中十分常见,一般来说公司所有的表都会以日期进行分区,以便提高查询效率。
我们还是以t_od_use_cnt为例,建表语句如下:
CREATE TABLE t_od_use_cnt (
platform string comment '平台 android,ios'
,app_version string comment 'app版本'
,user_id BIGINT comment '用户id'
,use_cnt INT comment '当日使用次数'
,is_active TINYINT comment '是否活跃'
) partitioned BY (date_8 INT comment '日期');
我们先使用set hive.cli.print.current.db=true;命令来显示当前库名,然后使用show tables;命令来查询当前库有哪些表,建表成功后,再使用desc命令查询表结构。执行效果如下:
hive> set hive.cli.print.current.db=true;
hive (default)> use app;
OK
Time taken: 0.619 seconds
hive (app)> show tables;
OK
t_od_use_cnt
Time taken: 0.262 seconds, Fetched: 1 row(s)
hive (app)> drop table t_od_use_cnt;
OK
Time taken: 1.303 seconds
hive (app)> create table t_od_use_cnt(
> platform string comment '平台 android,ios'
> ,app_version string comment 'app版本'
> ,user_id bigint comment '用户id'
> ,use_cnt int comment '当日使用次数'
> ,is_active tinyint comment '是否活跃'
> )
> partitioned by (date_8 int comment '日期');
OK
Time taken: 0.921 seconds
hive (app)> desc t_od_use_cnt;
OK
platform string 平台 android,ios
app_version string app版本
user_id bigint 用户id
use_cnt int 当日使用次数
is_active tinyint 是否活跃
date_8 int 日期
# Partition Information
# col_name data_type comment
date_8 int 日期
Time taken: 0.165 seconds, Fetched: 11 row(s)
hive (app)>
可以看到date_8作为分区字段创建好后表现的和普通字段完全一样。
[CLUSTERED BY (col_name, col_name, ...) [SORTED ,BY (col_name [ASC|DESC], ...)] INTO num_buckets BUCKETS] :
这个关键字是Hive中的分桶操作,数据分析师基本用不到,感兴趣的同学自行百度即可;
[ROW FORMAT row_format] :
这个关键字用于指定数据切分格式,一般使用 '\t' 作为列之间的切分格式。本博客中为了导入csv文件,统一使用逗号进行分割,建表语句如下:
CREATE TABLE t_od_use_cnt (
platform string comment '平台 android,ios'
,app_version string comment 'app版本'
,user_id BIGINT comment '用户id'
,use_cnt INT comment '当日使用次数'
,is_active TINYINT comment '是否活跃'
) partitioned BY (date_8 INT comment '日期') row format delimited fields terminated BY ',';
执行后查看表信息,效果如下:
hive> create table t_od_use_cnt (
> platform string comment '平台 android,ios'
> ,app_version string comment 'app版本'
> ,user_id BIGINT comment '用户id'
> ,use_cnt INT comment '当日使用次数'
> ,is_active TINYINT comment '是否活跃'
> ) partitioned BY (date_8 INT comment '日期') row format delimid fields terminated BY ',';
OK
Time taken: 0.313 seconds
hive> desc formatted t_od_use_cnt;
OK
# col_name data_type comment
platform string 平台 android,ios
app_version string app版本
user_id bigint 用户id
use_cnt int 当日使用次数
is_active tinyint 是否活跃
# Partition Information
# col_name data_type comment
date_8 int 日期
# Detailed Table Information
Database: default
Owner: root
CreateTime: Thu Apr 25 11:01:56 CST 2019
LastAccessTime: UNKNOWN
Protect Mode: None
Retention: 0
Location: hdfs://hadoop:9000/usr/hive/warehouse/t_od_use_cn
Table Type: MANAGED_TABLE
Table Parameters:
transient_lastDdlTime 1556161316
# Storage Information
SerDe Library: org.apache.hadoop.hive.serde2.lazy.LazySimpleSerD
InputFormat: org.apache.hadoop.mapred.TextInputFormat
OutputFormat: org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat
Compressed: No
Num Buckets: -1
Bucket Columns: []
Sort Columns: []
Storage Desc Params:
field.delim ,
serialization.format ,
Time taken: 0.244 seconds, Fetched: 36 row(s)
[STORED AS file_format] :
这个关键字用于设定数据在Hive中的存储格式,一般不指定,直接使用默认,或照公司其他表的存储格式即可。
在公司中需要查询既有表的建表格式时使用以下语句即可:
show create table tablename;
查询第六步所建外部表的建表语句,运行效果如下:
hive> show create table t_od_use_cnt;
OK
CREATE TABLE `t_od_use_cnt`(
`platform` string COMMENT 's� android,ios',
`app_version` string COMMENT 'appH,',
`user_id` bigint COMMENT '(7id',
`use_cnt` int COMMENT 'S.(!p',
`is_active` tinyint COMMENT '/&;�')
PARTITIONED BY (
`date_8` int COMMENT '�')
ROW FORMAT DELIMITED
FIELDS TERMINATED BY ','
STORED AS INPUTFORMAT
'org.apache.hadoop.mapred.TextInputFormat'
OUTPUTFORMAT
'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat'
LOCATION
'hdfs://hadoop:9000/usr/hive/warehouse/t_od_use_cnt'
TBLPROPERTIES (
'transient_lastDdlTime'='1556161316')
结果中文注释会显示乱码,这个问题需要重新编译jar包才能解决,在此就不提供解决办法了,有兴趣的同学自行百度即可,在工作里中文注释会有运维同学帮搞定~
可以看到其中有很多我们建表时并没有输入的语句,这些都是系统默认的设置,有兴趣的同学逐项百度,这里就不一一介绍了,因为工作中真的用不到~
能看到这里的同学,就右上角点个赞顺便关注我吧,3Q~