前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Hive基础学习

Hive基础学习

作者头像
超哥的杂货铺
发布2019-12-18 10:51:40
6220
发布2019-12-18 10:51:40
举报
文章被收录于专栏:超哥的杂货铺超哥的杂货铺

本节我们主要来学习一些hive的命令操作,同时探究一下Hive,HDFS,MySQL之间的联系,从而更好的理解其内部原理。

常用的基础命令
代码语言:javascript
复制
#此处的命令都是指在hive命令行下执行的命令,所有的命令别忘记以分号结尾。
hive> show databases;#查看当前数据库列表
hive> create databases dbname;#创建一个名称为dbname的数据库
hive> use databasename;#将当前的数据库切换为databasename
hive> show tables;#查看当前数据库中有哪些表
hive> desc tbname;#查看表结构,包括字段类型,注释等
Hive的数据类型

hive基本数据类型

hive集合数据类型

注:图片来自《hive编程指南》
这里先简单了解一下Hive的数据类型,本节我们暂时不会用到太多很复杂的类型。
建表

假设我们现在建立一张student表,它有两个字段,id(int)name(string)

代码语言:javascript
复制
hive> create database learn;#创建数据库learn
hive> use learn;#切换到learn数据库
hive> create table student(id int, name string);#创建表student
hive> show create table student;#查看建表语句

创建表,查看建表语句

我们通过show create table student;命令查看student表建立时一些详细信息。关注一下LOCATION的值为:hdfs://localhost:8020/user/hive/warehouse/learn.db/student,猜测这是一个HDFS的文件路径,我们通过浏览器验证一下:

在浏览器中查看student表的location

可以看到,我们建立的student表是HDFS上的一个目录(文件夹),目录的位置就是LOCATION对的值。

将本地文件加载到Hive表

本地文件:当前目录下的student.txt,字段之间用空格分割,

代码语言:javascript
复制
1 zhangsan
2 lisi
3 wangwu
代码语言:javascript
复制
hive> load data local inpath 'student.txt' into table student;

加载本地数据

加载成功之后,我们先来看一下HDFS中student目录,如下图所示,可以看到该目录下出现了一个student文件。

查看HDFS中student目录

然后用hive命令查询一下student表。

代码语言:javascript
复制
hive> select * from student;
OK
NULL    NULL
NULL    NULL
NULL    NULL
Time taken: 0.139 seconds, Fetched: 3 row(s)

可以看到结果虽然是有三行,但全部否是null。如果执行select count(*) from student;也能输出结果为3。

查询student表的行数

出现这种情况是,我们建表时没有指定数据列之间的分隔符,hive默认的字段分隔符是\001,即ASCII码的第一个字符Control-A,而我们的文件的分隔符是空格,二者不一致是导致数据不能正确加载的原因。

接下来我们创建一个新的表并指定分隔符为\t,即tab符,然后重新加载以\t分割的本地文件。

代码语言:javascript
复制
hive> create table teacher(id int, name string) row format delimited fields terminated by '\t';#创建teacher表并指定行分隔符为'\t'
hive> load data local inpath 'teacher.txt' into table teacher;#实际运行加了overwrite,表示覆盖表中已有的数据,如果不加overwrite就会在已有的数据后直接添加。

加载tab符分割的数据

创建teacher表同样在HDFS中建立了相应的目录,load数据同样也将本地的数据加载到了相应的目录中。

HDFS中查看teacher目录

将HDFS文件加载到Hive表

我们按照以下的步骤进行操作:

①在本地建立course.txt文件,写入三行内容,字段之间用空格分割。

代码语言:javascript
复制
1    语文
2    数学
3    体育

②将course.txt上传到HDFS中并检查是否上传成功。

③在hive中建立course表,指定分隔符为tab符

④执行load data inpath '/course.txt' into table course命令,加载HDFS数据到course表中。

⑤查询course表中的数据,验证是否成功加载

⑥查看HDFS中是否依然存在course.txt文件。

从执行的结果我们可以看出,从HDFS中加载数据时,是将HDFS中的文件直接移动到了表对应的HDFS目录中(内部表)。

理解Hive的元数据

Hive环境搭建的时候我们使用MySQL存储了Hive元数据,并且在初始化时生成了很多mysql数据表。那么它们有什么作用呢?我们来看一下TBLS,COLUMNS_V2,SDS三个表的信息,很容易联系到我们前面创建的表。

代码语言:javascript
复制
mysql> use metastore;#切换到我们之前创建的元数据库。
mysql> show tables;
+---------------------------+
| Tables_in_metastore       |
+---------------------------+
| BUCKETING_COLS            |
| CDS                       |
| COLUMNS_V2                |
| COMPACTION_QUEUE          |
| COMPLETED_TXN_COMPONENTS  |
| DATABASE_PARAMS           |
| DBS                       |
| DB_PRIVS                  |
| DELEGATION_TOKENS         |
| FUNCS                     |
| FUNC_RU                   |
| GLOBAL_PRIVS              |
| HIVE_LOCKS                |
| IDXS                      |
| INDEX_PARAMS              |
| MASTER_KEYS               |
| NEXT_COMPACTION_QUEUE_ID  |
| NEXT_LOCK_ID              |
| NEXT_TXN_ID               |
| NOTIFICATION_LOG          |
| NOTIFICATION_SEQUENCE     |
| NUCLEUS_TABLES            |
| PARTITIONS                |
| PARTITION_EVENTS          |
| PARTITION_KEYS            |
| PARTITION_KEY_VALS        |
| PARTITION_PARAMS          |
| PART_COL_PRIVS            |
| PART_COL_STATS            |
| PART_PRIVS                |
| ROLES                     |
| ROLE_MAP                  |
| SDS                       |
| SD_PARAMS                 |
| SEQUENCE_TABLE            |
| SERDES                    |
| SERDE_PARAMS              |
| SKEWED_COL_NAMES          |
| SKEWED_COL_VALUE_LOC_MAP  |
| SKEWED_STRING_LIST        |
| SKEWED_STRING_LIST_VALUES |
| SKEWED_VALUES             |
| SORT_COLS                 |
| TABLE_PARAMS              |
| TAB_COL_STATS             |
| TBLS                      |
| TBL_COL_PRIVS             |
| TBL_PRIVS                 |
| TXNS                      |
| TXN_COMPONENTS            |
| TYPES                     |
| TYPE_FIELDS               |
| VERSION                   |
+---------------------------+
53 rows in set (0.00 sec)
代码语言:javascript
复制
mysql> select * from TBLS;#存放我们已经建立的表,具体字段如图所示
mysql> select * from COLUMNS_V2;#存放表的字段,CD_ID是外键
mysql> select * from SDS;#存放表的LOCATION和格式信息

注:这个表横向太长了。因此截成了两段,凑合看。感兴趣的可以自己动手试试。

TBS存放的是我们已经创建的表,COLUMNS_V2存放了标的字段信息,SDS存放了表的LOCATION和格式信息。其他表的信息我们也可以通过看里面的内容理解其作用~请读者自行了解~

其他命令

查看某个表的基本信息:

代码语言:javascript
复制
hive> desc student;#查看表的字段及其类型
OK
id                      int
name                    string
Time taken: 0.069 seconds, Fetched: 2 row(s)

hive> desc formatted student;#查看表的详细信息,包括字段,位置,类型,存储信息等
OK
# col_name                data_type               comment

id                      int
name                    string

# Detailed Table Information
Database:               learn
Owner:                  chenghengchao
CreateTime:             Sat Jun 08 00:31:45 CST 2019
LastAccessTime:         UNKNOWN
Protect Mode:           None
Retention:              0
Location:               hdfs://localhost:8020/user/hive/warehouse/learn.db/student
Table Type:             MANAGED_TABLE
Table Parameters:
    COLUMN_STATS_ACCURATE   true
    numFiles                1
    numRows                 0
    rawDataSize             0
    totalSize               27
    transient_lastDdlTime   1559973358

# 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.059 seconds, Fetched: 32 row(s)

在hive命令下直接操作HDFS:

代码语言:javascript
复制
# 在hive下直接操作HDFS,建立data文件夹并上传本地文件到HDFS,命名为a.txt 和b.txt
hive> dfs -mkdir /data;
hive> dfs -put student.txt /data/a.txt;
hive> dfs -put student.txt /data/b.txt;

表的类型有两种MANAGED_TABLE和EXTERNAL_TABLE。

hive内部表和外部表的区别 1)创建表时:创建内部表时,会将数据移动到数据仓库指向的路径;若创建外部表,仅记录数据所在的路径, 不对数据的位置做任何改变。 2)删除表时:在删除表的时候,内部表的元数据和数据会被一起删除,而外部表只删除元数据,不删除数据。这样外部表相对来说更加安全些,数据组织也更加灵活,方便共享源数据 reference:https://blog.csdn.net/u010886217/article/details/83796151 reference:https://www.jianshu.com/p/ac2eca9181be reference:https://blog.csdn.net/qq_36743482/article/details/78393678

代码语言:javascript
复制
#创建外部表并指向已有的data目录,如果指定的location不存在则会创建。
hive> create external table ext_student(id bigint,name string) row format delimited fields terminated by '\t' location '/data';
OK
Time taken: 0.064 seconds
hive> select * from ext_student;
OK
1   zhangsan
2   lisi
3   wangwu
1   zhangsan
2   lisi
3   wangwu
Time taken: 0.034 seconds, Fetched: 6 row(s)

查询结果显示了6条记录,前3条和后3条是一样的。这是因为/data 下面有两个文件a.txt 和b.txt,每个文件有3行有数据。如果再上传一次teacher文件到/data目录下。在看ext_student中的数据

代码语言:javascript
复制
hive> dfs -put teacher.txt /data/c.txt;
hive> select * from ext_student;
OK
1    zhangsan
2    lisi
3    wangwu
1    zhangsan
2    lisi
3    wangwu
1    赵老师
2    王老师
3    刘老师
4    邓老师
Time taken: 0.032 seconds, Fetched: 10 row(s)

可见,指定的location,即/data目录下的三个文件的数据都被加载到了ext_student中。事实上,无论是外部表还是内部表,只要把某个文件放到表的目录下,就会被扫描并被查询出来。查询的执行过程是先通过TBLS表找到student表,然后根据表id到COLUMNS_V2表查找这张表都有哪些字段,然后再根据表id到SDS表中查找应该到HDFS的那个目录下去查找数据。

Hive分区表
代码语言:javascript
复制
hive> create external table players(id bigint,name string) partitioned by (nation string) row format delimited fields terminated by '\t' location '/players';#执行后会在HDFS上创建/players目录,这是一个以nation分区的表
OK
Time taken: 0.095 seconds
hive> dfs -put china.txt /players;#将本地的china.txt上传到HDFS的players目录下
hive> select * from players;#查询players表,发现结果是空的,但如果从浏览器中查看players牡蛎,发现文件china.txt存在。
OK
Time taken: 0.041 seconds

查询没有数据的原因,是没有上传文件到指定分区。我们换一种方式。

代码语言:javascript
复制
hive> load data local inpath 'china.txt' into table players partition(nation='China');
Loading data to table learn.players partition (nation=China)
Partition learn.players{nation=China} stats: [numFiles=1, numRows=0, totalSize=38, rawDataSize=0]
OK
Time taken: 0.242 seconds
hive> select * from players;
OK
1    zhangjike   China
2    yijianlian  China
3    subingtian  China
Time taken: 0.045 seconds, Fetched: 3 row(s)

我们上传文件时指定分区,就能查询出结果。此时在HDFS上出现了一个nation=China的目录,china.txt被上传到了改该目录下。

我们试一下手动创建nation=USA目录,并将usa.txt上传到该目录。再查询players

代码语言:javascript
复制
hive> dfs -mkdir /players/nation=USA;
hive> dfs -put usa.txt /players/nation=USA;
hive> select * from players;
OK
1    zhangjike   China
2    yijianlian  China
3    subingtian  China
Time taken: 0.042 seconds, Fetched: 3 row(s)

查询的结果没有USA分区的数据,但从浏览器中查看确实已经存在了/players/nation=USA/usa.txt,并且usa.txt是有数据的。这是因为元数据库中没有记录USA这个分区。(看SDS表的话,只有nation=China的记录)。但如果此时使用load命令加载数据,则可以创建nation=USA的分区。在SDS表中也会出现nation=USA。

代码语言:javascript
复制
hive> load data local inpath 'usa.txt' into table players partition(nation='USA');
Loading data to table learn.players partition (nation=USA)
Partition learn.players{nation=USA} stats: [numFiles=2, numRows=0, totalSize=50, rawDataSize=0]
OK
hive> select * from players;
OK
1    zhangjike   China
2    yijianlian  China
3    subingtian  China
1    Curry   USA
2    Phelps  USA
3    Woods   USA
1    Curry   USA
2    Phelps  USA
3    Woods   USA
Time taken: 0.037 seconds, Fetched: 9 row(s)

查询的结果中出现了USA分区,但是有重复。这是因为nation=USA目录下有两个相同内容的文件。原因是通过load命令将目录“变”为分区的同时,也加载了相同的一份数据。我们也可以看出:分区一定是一个目录,但目录不一定是分区。而且如果删除了分区,文件夹可以继续存在,如果删除了文件夹,分区也继续存在。

我们也可以通过另一种方式修改(增加)分区,如下面命令所示。如果直接运行该命令,会在HDFS上创建目录nation=Other。如果我们先用mkdir创建nation=Other目录,再使用该命令,也可以将目录“变”为分区,此时目录下的文件就会被加载到表中,读者可以自行验证。

代码语言:javascript
复制
hive> alter table players add partition(nation='Other') location '/players/nation=Other';

再总结一下查看和删除分区的命令。

代码语言:javascript
复制
hive> show partitions players;#查看分区
OK
nation=China
nation=Other
nation=USA
Time taken: 0.047 seconds, Fetched: 3 row(s)
hive> alter table players drop if exists partition (nation='Other');#删除某个分区
Dropped the partition nation=Other
OK
Time taken: 0.068 seconds

使用了分区之后,最大的好处是能提高查询的速度,同时也对数据进行了更细粒度的划分。可以使用where关键字限制分区。

代码语言:javascript
复制
hive> select * from players where nation = 'China';
OK
1    zhangjike   China
2    yijianlian  China
3    subingtian  China
Time taken: 0.074 seconds, Fetched: 3 row(s)
hive> select * from players where nation = 'USA';
OK
1    Curry   USA
2    Phelps  USA
3    Woods   USA
1    Curry   USA
2    Phelps  USA
3    Woods   USA
Time taken: 0.047 seconds, Fetched: 6 row(s)
总结

本文我们对Hive的一些基础知识进行了学习,包括查看数据库,查看表的基本命令,如何建表并加载数据,hive元数据的存储位置,hive分区表与HDFS的关系等。通过学习我们对Hive底层原理有了更为深刻的认识。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-06-09,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 超哥的杂货铺 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 常用的基础命令
  • Hive的数据类型
    • 注:图片来自《hive编程指南》
      • 这里先简单了解一下Hive的数据类型,本节我们暂时不会用到太多很复杂的类型。
      • 建表
      • 理解Hive的元数据
      • 其他命令
      • Hive分区表
      • 总结
      相关产品与服务
      云数据库 MySQL
      腾讯云数据库 MySQL(TencentDB for MySQL)为用户提供安全可靠,性能卓越、易于维护的企业级云数据库服务。其具备6大企业级特性,包括企业级定制内核、企业级高可用、企业级高可靠、企业级安全、企业级扩展以及企业级智能运维。通过使用腾讯云数据库 MySQL,可实现分钟级别的数据库部署、弹性扩展以及全自动化的运维管理,不仅经济实惠,而且稳定可靠,易于运维。
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档