Fork me on GitHub

Hive Day02


课程回顾

yarn的产生背景

hadoop1.0 mapreduce存在严重的缺陷

  1. 扩展性不足
  2. 资源利用率低
  3. 存在单点故障

yarn的架构

主从
主:resourcemanager
​ ASM:applicationsmanager
​ 管理MRAppMaster
​ scheduler:调度器
​ FIFO
​ FAIR
​ Capacity

从:nodemanager
​ container 是一个虚拟的资源容器

MRAppMaster: 每一个应用程序的老大;回忆job提交过程
​ 负责管理整个应用程序;
​ 给maptask和reducetask申请资源;
​ 启动maptask和reducetask任务;
​ 跟踪maptask 和reducetask进行和状态;
​ 对失败的maptask和reducetask重启;

hive的数据组织格式

同关系型数据库;便于数据的管理,将不同的模块的数据存储在不同的数据库中;

表的属性:内部表、外部表
按照功能分:分区表、分桶表

没有一个表即使内部表;又是外部表的;内部表和外部表是相互对立的;

内部表

表的数据hive自己进行管理的

可以自己决定数据的删除或添加

内部表在进行删除的时候,原始数据和元数据(有关当前删除的表的记录的)是一并删除的;

内部表的数据存放在hive的家目录中;

外部表

不在hive的家目录中的所有数据都可以称之为外部表;(主要是看权限)

表的数据是hdfs管理的;hive只有权利使用;没有权利删除;

外部表来说,删除表的时候;原始数据不能删除;元数据会被删除;

对于外部表来说,hive仅仅相当于创建了一个和hdfs上的数据关联的表;

分区表(不同于mapreduce的分区)

当数据量比较大的时候;在进行查询的时候,如果每一次都进行全表扫描;必然造成查询性能低;这个时候就出现了分区表的概念;

分区表将原来表的原始数据进行分目录存储;相当于对原始表进行一个区块划分;将原来的表分成了很多的区域;这样做的目录就是便于查询;在查询的时候可以减少查询的范围;

非分区表的数据存储

hdfs://hdp01:9000/user/hive/warehouse/text.db/stu
非分区表的一个表的所有数据读存储在上面的表的对应目录下
非分区表中,一个表对应一个目录;

分区表的表现形式

分区表:
将表中的数据分别存储在不同的区域下;将表中的不同区的数据分别存储在不同的目录下;

分区表一般指定一个分区字段;分区字段选择的依据是查询的过滤字段
比如:学生信息表,查询的时候通常按照班级进行查询;分区字段就是班级;

分区表这里一个分区就会对应一个目录结构;
我们在查询的过程中,按照分区字段进行过滤查询;这个时候只会扫描指定分区字段值的目录;

分区表总结:

  1. 分区表对应的不同的目录结构
  2. 减少查询的时候的数据扫描范围;提升查询性能;

分桶表(类似mapreduce的分区的概念)

作用:

  1. 提升抽样的性能
  2. 提升join的性能

目录划分:
​ 将不同的桶的数据进行分别存储在不同的文件中;
​ 分桶表来说:选择一个分桶字段(相当于mapreduce中的分区字段)
​ 选择完成分桶字段之后,指定桶的个数(分区个数/reducetask的个数)
​ 分桶的数据划分:分桶字段.hash%分桶个数;
​ 余数为0----桶0
​ 余数为1----桶1

最后的数据目录:
数据量比较大的时候;先进行数据抽样分析;抽取样本数据进行测试;
样本数据的要求;具有代表性;抽取的数据要足够散列;桶数据就是这样的数据;可以直接拿一个桶的数据作为样本数据;

视图

主要为了提升hql语句的可读性;

  1. hive中的视图只存在逻辑视图,不存在物化视图
    逻辑视图:只存储视图代表的hql语句,不会进行执行;
    物化视图:将视图对应的查询语句执行出来结果;
  2. hive的视图仅仅是相当于一条查询语句的快捷方式;
  3. hive中的视图,在查询视图的时候才会真正的执行;
  4. hive中的视图不支持insert 和update等操作,只支持查询操作

数据存储

元数据

元数据就是存储hive中的表;-------新政策V字
元数据存储:存储在关系型数据库的;默认为derby数据库;一般改为mysql数据库
元数据对应的myslq的位置;

<property>
    <name>javax.jdo.option.ConnectionURL</name>
    <value>jdbc:mysql://localhost:3306/myhive?createDatabaseIfNotExist=true</value>
    <description>JDBC connect string for a JDBC metastore,myhive表示存储hive元数据在mysql中的数据库名</description>
    <!-- 如果 mysql 和 hive 在同一个服务器节点,那么请更改 hadoop02 为 localhost -->
</property>

元数据的结构:

  1. hive中的数据库的描述信息
    DBS表存储的是hive的数据库的描述信息
    ​ 原始数据的hdfs的存储目录
    每当hive中创建一个数据库的时候,这个表中就会添加一条数据;

  2. hive中的表的描述信息的元数据;TBLS
    每当hive中创建一个表,这个表中就会添加一条数据;
    所属库id 表明 表类型

  3. hibe中表的字段的描述信息:COLUMNS_V2
    所属表id 字段名 字段类型 字段顺序
    表中每当添加一个字段,这个表中就会添加一条数据

注意:元数据信息可以修改的;一旦元数据修改;会造成表结构修改;
hive的表结构(库信息,表信息,字段信息)相关数据,从元数据加载的;
所以元数据信息慎重修改;

原始数据

原始数据:表中存储的数据
存储在hdfs上,默认为/user/hive/warehouse
读取的配置文件:
hive-default.xml

<property>
    <name>hive.metastore.warehouse.dir</name>
    <value>/user/hive/warehouse</value>
    <description>hive default warehouse, if nessecory, change it</description>
</property>

修改完成;重新进入hive的客户端就可以;
注意:修改生效;从修改之后的创建库/表的数据库才会改;之前的不会修改;

原始数据存储的目录结构:
当前目录下存储的是该表对应的原始数据文件;
这就是hive的数据组织形式;

hive的ddl

data define language

库的操作

创建数据库

create database db_name;

切换库

use db_name;

查看库列表

show databases;
show databases like "text*";

查看数据库的描述信息

desc database db_name;

查看正在使用的库

select current_database();

删除库:

drop database db_name; # 只能删除空的库;
drop database db_name restrict; # restrict 严格模式下的删除库,会进行库的检查;如果不是空库,则不允许删除;
drop database db_name cascade; # 可以删除非空数据库

防止报异常操作

if not existsif exists
在创建库和删除库的时候,为了防止异常;

# if not exists 建库;
create database if not exists db_name;
# if exists 删除库
drop database if exists db_name;

这两个操作同样适用于表和分区的操作;

表的操作

创建表

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]

说明:

  1. EXTERNAL 关键字;加上这个关键字,建的表是外部表;不加这个关键字;建的表就是内部表;

  2. IF NOT EXISTS 防止报异常的

  3. Comment 指定列或表的描述信息

  4. PARTITIONED BY (col_name data_type [COMMENT col_comment], ...) 指定分区字段,
    PARTITIONED BY (分区字段名 分字段类型 Comment 分区字段的描述信息)
    注意: 分区字段一定不能在建表字段中

  5. CLUSTERED BY (col_name, col_name, ...) [SORTED BY (col_name [ASC|DESC], ...)] INTO num_buckets BUCKETS] 指定分桶的
    CLUSTERED BY (col_name, col_name, ...) 分桶字段
    注意:分桶字段一定是建表字段中的一个或几个;
    SORTED BY (col_name [ASC|DESC], ...) 指定的是每一个桶表中的排序规则
    INTO num_buckets BUCKETS 指定桶的个数

  6. ROW FORMAT row_format 指定分隔符
    fields terminated by 列分隔符
    lines terminated by 行分隔符
    map keys terminated by map集合的key和vlaue的分隔符

  7. STORED AS file_format 指定原始数据的存储格式
    textfile 文本格式 默认的方式
    rcfile 行列格式 在行的方向上切分数据存储的块;保证一行在一个数据块中
    sequencefile 二进制存储格式

  8. LOCATION hdfs_path 指定原始数据的存储位置;这里没有指定,则读取配置文件中的;如果制定了则覆盖配置文件中的;
    一定是hdfs上的路径

hive的原始数据的存储的配置:

  1. hive-default.xml
  2. hive-site.xml
  3. 建表语句中的LOCATION

加载顺序为 1->2->3;
生效顺序: 最后加载的最终生效;

案例

创建一个内部表

create table if not exists student 
(grade int,stue_id int,name string, 
yuwen string ,shuxue string,yingyu string) 
comment "student score" 
row format delimited 
fields terminated by "\t" 
lines terminated by "\n" 
stored as textfile 
location "/user/data/student";
hive> create database bd1808;
OK
Time taken: 12.601 seconds
hive> show databases;
OK
bd1808
default
Time taken: 0.339 seconds, Fetched: 2 row(s)
hive> 
hive> create table if not exists student 
    > (grade int,stue_id int,name string, 
    > yuwen string ,shuxue string,yingyu string) 
    > comment "student score" 
    > row format delimited 
    > fields terminated by "\t" 
    > lines terminated by "\n" 
    > stored as textfile 
    > location "/user/data/student";
OK
Time taken: 0.696 seconds
hive>
hive> desc student
    > ;
OK
grade               	int                 	                    
stue_id             	int                 	                    
name                	string              	                    
yuwen               	string              	                    
shuxue              	string              	                    
yingyu              	string              	                    
Time taken: 0.236 seconds, Fetched: 6 row(s)
hive> 

创建一个外部表

create external table if not exists student_external
(grade int,stue_id int,name string, 
yuwen string ,shuxue string,yingyu string) 
comment "student score" 
row format delimited 
fields terminated by "\t" 
lines terminated by "\n" 
stored as textfile 
location "/user/data/student_external";
hive> create external table if not exists student_external
    > (grade int,stue_id int,name string, 
    > yuwen string ,shuxue string,yingyu string) 
    > comment "student score" 
    > row format delimited 
    > fields terminated by "\t" 
    > lines terminated by "\n" 
    > stored as textfile 
    > location "/user/data/student_external";
OK
Time taken: 0.275 seconds
hive> show tables;
OK
student
student_external
Time taken: 0.125 seconds, Fetched: 2 row(s)
hive> desc student_external
    > ;
OK
grade               	int                 	                    
stue_id             	int                 	                    
name                	string              	                    
yuwen               	string              	                    
shuxue              	string              	                    
yingyu              	string              	                    
Time taken: 0.145 seconds, Fetched: 6 row(s)
hive> 

创建一个分区表

选择一个分区字段:根据过滤条件
分区字段:grade

creat external table if not exists student_ptn
(stu_id int,name string,yuwen string,shuxue string,yingyu string) COMMENT 'student score' 
partitioned by (grade int) 
row format delimited fields terminated by '\t';

创建一个分桶表

分桶字段:name
排序:yuwen shuxue yingyu desc
桶个数 3
分桶表的字段一定在建表语句中

creat table if not exsits student_buk 
(grade int,stu_id int,name string,yuwen string,shuxue string,yingyu string) 
clustered by (name) sorted by (yuwen desc,shuxue desc,yingyu desc) 
into 3 buckets
row format delimited fields terminated by "\t";

进行表复制

关键字 like

create table if not exists stu_like like student;
create table if not exists stu_like01 like student_external;

只会复制表结构,表的属性(表的存储位置,表的类型)不会复制的;
默认为内部表;

ctas语句建表

create table tablename as select ... from ...

将sql语句的查询结果存放在一个表中;

查看表的描述信息

desc table_name; # 只能查看表的字段信息
desc extended table_name # 查看表的详细信息;所有的信息放在一行的
desc formatted table_name; # 格式化显示表的详细信息;

重点: desc formatted t_name

hive> desc extended student_external;
OK
grade               	int                 	                    
stue_id             	int                 	                    
name                	string              	                    
yuwen               	string              	                    
shuxue              	string              	                    
yingyu              	string              	                    
	 	 
Detailed Table Information	Table(tableName:student_external, dbName:default, owner:hadoop, createTime:1542076631, lastAccessTime:0, retention:0, sd:StorageDescriptor(cols:[FieldSchema(name:grade, type:int, comment:null), FieldSchema(name:stue_id, type:int, comment:null), FieldSchema(name:name, type:string, comment:null), FieldSchema(name:yuwen, type:string, comment:null), FieldSchema(name:shuxue, type:string, comment:null), FieldSchema(name:yingyu, type:string, comment:null)], location:hdfs://hdp01:9000/user/data/student_external, inputFormat:org.apache.hadoop.mapred.TextInputFormat, outputFormat:org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat, compressed:false, numBuckets:-1, serdeInfo:SerDeInfo(name:null,serializationLib:org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe, parameters:{serialization.format=	, line.delim=, field.delim=	}), bucketCols:[], sortCols:[], parameters:{}, skewedInfo:SkewedInfo(skewedColNames:[], skewedColValues:[], skewedColValueLocationMaps:{}), storedAsSubDirectories:false), partitionKeys:[], parameters:{transient_lastDdlTime=1542076631, comment=student score, EXTERNAL=TRUE}, viewOriginalText:null, viewExpandedText:null, tableType:EXTERNAL_TABLE, rewriteEnabled:false)	
Time taken: 0.15 seconds, Fetched: 9 row(s)
hive>
    > desc formatted student_external;
OK
# col_name            	data_type           	comment             
	 	 
grade               	int                 	                    
stue_id             	int                 	                    
name                	string              	                    
yuwen               	string              	                    
shuxue              	string              	                    
yingyu              	string              	                    
	 	 
# Detailed Table Information	 	 
Database:           	default             	 
Owner:              	hadoop              	 
CreateTime:         	Tue Nov 13 10:37:11 CST 2018	 
LastAccessTime:     	UNKNOWN             	 
Retention:          	0                   	 
Location:           	hdfs://hdp01:9000/user/data/student_external	 
Table Type:         	EXTERNAL_TABLE      	 
Table Parameters:	 	 
	EXTERNAL            	TRUE                
	comment             	student score       
	transient_lastDdlTime	1542076631          
	 	 
# 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:	 	 
	field.delim         	\t                  
	line.delim          	\n                  
	serialization.format	\t                  
Time taken: 0.203 seconds, Fetched: 34 row(s)

查看表的列表

show tables; # 查看当前数据库的表列表信息;
show tables in db_name; # 查看指定数据库的表列表信息
show tables like "student*";
show partitions t_name; # 查询指定表下的所有分区信息;

修改表

表的重命名

alter table t_name rename to new_tname;
alter talbe stu_like01 rename to student_copy;

或者修改元数据信息也可以重命名表名;

修改表的列

增加列
alter table t_name add columns(name type);
alter table student_copy add columns(content string);

增加列的时候一定要添加数据类型

修改列
  1. 修改列名

    alter table t_name change oldname newname type;
    alter table student_copy change content text string;
    
  2. 修改列类型

    alter table t_name change oldname newname type;
    alter table student_copy change grade grade string;
    alter table student_copy change text text int;
    

hive的2.0版本中对类型转换座限制了;只允许 小类型 转换 大类型;
不允许 大类型 转换 小类型;
例如 string 不能转换为 int;

替换列
alter table t_name replace columns(name type);
alter table stu_test replace coumns(id int);
删除列

不支持

修改分区信息

添加分区

根据分区字段进行添加;
手动添加分区

alter table t_name add partition(name=value);
alter table student_ptn add partition(grade=1303);
alter table student_ptn add partition(grade=1304);

添加多个分区
alter table student_ptn add partition(grade=1305) partition(grade=1306) partition(grade=1307);
修改分区的存储位置

分区的默认存储位置:是在表的目录下创建的分区目录;
我们可以手动指定某一个分区的存储位置

  1. 添加的分区时候进行指定

    alter table student_ptn add partition(grade=1308) location '/user/student/1308';
    
  2. 对于已经添加的分区修改存储位置;添加数据的时候才会生效,不会立即生效;

    alter table t_name partition(name=value) set location '/user/student/1303';
    
删除分区
alter table t_name drop partition(name=value)

表数据的清空

truncate table t_name;
truncate table t_name partition(name=value); # 清空某一个分区的数据;

删除表

drop table if exists tname;

查看详细建表语句

show create table t_name;

查看数据库的详细信息

desc database extended db_name;

hive的dml

data manager language

表的数据插入

load方式

load data [local] inpath path into table t_name;

说明:local:加上local关键字,代表的是数据从本地(客户端处)导入;不加local关键字,代表的是数据从hdfs上导入的;

数据从本地导入

load data local inpath '/home/hadoop/tmpdata/score.txt' into table student_external;

本质是将数据从本地上传到hdfs的表存储目录下

直接将本地的数据上传到hive的表的hdfs的目录下

hadoop fs -put score.txt /user/data/sutdent_external/score1.txt
数据依然可以通过hive查询到

hive中的表就是hdfs一个目录的数据的管理者;只要在这个目录下添加数据;数据不管符不符合规则都会被hive加载到;

数据从hdfs加载

load data inpath '/sco_in/score.txt' into table studetn_external;

文件没有冲突;在文件上传到表的管理空间的时候会对重名的文件进行重命名;score_copy_1.txt
注意:上面的两张方式,追中结果都是将数据放在hive的表空间中

insert的方式

单条数据插入 同mysql的单挑数据插入

不推荐使用
一次只能插入一条数据

insert into talbe t_name values();

insert into table student values(1303,2345,"xh",23,53,15);

这种插入方式会转换为MR任务,执行效率低;

将数据线插入到一个临时表中values_tmp_table_2,在将这个临时表中的数据读取写出到hive表的管理空间中;

单重数据插入

一次性插入多条数据

将sql查询语句的查询结果进行插入

insert into table t_name select ... 
insert into table student select * form student_external where yuwen>80;

缺点:不能一次将数据插入到多个表中;每次插入都需要对表进行扫描;

需求:

insert into table student select * from student_external where yuwen>80;
insert into table student01 select * from student_external where shuxue>90;

每次插入数据,都需要对student_external表进行扫描;

多重数据插入

对表扫描一次,将数据插入到多个表中,或者是同一个表的多个分区中;
语法:

from t_name 
insert into table t_name1 select ... where ... 
insert into table t_name2 select ... where ...

对上面的需求使用多重数据插入:

from student_external
insert into table stu01 select * where yuwen>80;
insert into table stu02 select 8 where shuxue>90;

两种特殊表的数据插入问题:

分区表的数据插入

静态分区数据插入

静态:表的分区值是手动静态指定的;
在数据插入的时候需要手动指定分区的值;

load的方式

load data [local] inpath '' into table t_name partition(name=value);

说明:partition用于指定分区名的 后面的括号中给的就是分区名
分区名 key=value;

load data local inpath '/home/hadoop/tmpdata/score.txt' into table student_ptn partition(grade=1303);

注意: 这种方式进行数据加载的时候;不会进行数据检查的;在用这种方式进行加载的时候一定要十分确定数据是这个分区的
生产中:分区字段使用最多的是时间戳;
采集数据的时候:今天收集昨天的数据;也是按照时间收集的;

上面的这种方式在进行数据加载的时候;会按照建表语句中的字段顺序进行解析加载的文件中的列;最后一个字段取进行加载数据的时候指定的分区值;

这种方式加载数据的时候,分区字段不需要在原始数据中

insert的方式,可以添加过滤条件

将指定的数据放在指定的分区中

单重数据插入的方式
insert into table t_name partition(name=value) select ... from ... where ...;

insert into table student_ptn partitiion(grade=1304) select stu_id,name,yuwen,shuxue,yingyu from student_external where grade=1304;

这种方式在插入数据的时候,一定要注意查询的字段和分区表中的字段的要匹配

多重数据插入的方式

一次扫描数据,插入到多个分区中;

from t_name
insert into table t_name1 partition(name=value) select ... where ...
insert into table t_name2 partition(name=value) select ... where ...;
from student_external
insert into table student_ptn partition(grade=1305) select stu_id,name,yuwen,shuxue,yingyu where grade=1305
insert into table student_ptn  partition(grade=1306) select stu_id,name,yuwen,shuxue,yingyu where grade=1306;

这种方式比较普遍,在数据插入的时候可以对数据进行检查;

缺点: 数据足够大,分区足够多的时候,分区的值不确定的时候;这个时候静态分区比较麻烦

动态分区数据插入

分区的值随着数据的插入动态生成的
分区是根据数据动态生成的
动态分区中分区字段的值是根据数据来的,数据在查询的时候需要将分区字段也查询出来;
数据插入方式只能使用insert的方式不能使用locad的方式

insert into table t_name partition(分区字段(分区字段不需要值)) select ... from ...;

案例

insert into table student_ptn partition(grade) select stu_id,name,yuwen,shuxue,yingyu,grade from student_external;

关闭严格模式:

set hive.exec.dynamic.partition.mode=nonstrict;

设置为本地模式

set hive.exec.mode.local.auto=true;

默认分区字段都在最后的;

注意:动态分区中,必须将分区字段放在查询语句的最后;
原因:分区表中会自动将分区字段放在表的普通字段的后面;

动态分区和静态分区的区别

  1. 静态分区 分区手动指定的
    动态分区的分区根据数据自动生成的
  2. 静态分区可能存在某一个分区为空的情况
    动态分区每一个分区中至少都有一条数据的;不存在空分区的可能;
  3. 动态分区比较消耗性能;动态分区中如果设置,reducetask的个数;针对的是每一个动态分区都有效的;set reducetasks=3;每一个分区中的数据都会启动3个reducetask;在动态分区中一定要慎重使用reducetask的个数

多级分区

分区字段找过一个分区叫做多级分区;多级分区之间必然存在从属关系;
partition(name,age)
name称为高级分区,一级分区
age 二级分区

分区的时候,现根据高级分区,再根据低级分区

创建一个多级分区表
分区字段:过滤条件

输入写入:

  1. 两个分区都是静态的

    alter table sudent_ptn01 add partition(grade=1303,yuwen='34');
    
  2. 只有一个是静态分区;另外一个是动态分区;
    这个静态分区只能是高级分区;insert的时候可以指定;

不能写成:

alter table student_ptn-1 add partition(grade=1304)
load 
load data local inpath '/home/hadoop/tmpdat/score.txt' into table student_ptn01 partition(grade=1303,yuwen='34');

insert 
insert into table student_ptn01 partition(grade=1303,yuwen)  select stu_id,name,shuxue,yingyu,yuwen from student_external;
  1. 全部动态
insert into table student_ptn01 partition(grade,yuwen)  select stu_id,name,shuxue,yingyu,grade,yuwen from student_external;

先查询一级分区,在查询二级分区;

分桶表的数据插入

  1. load方式:不支持
load data local inpath "" into table student_buk;

分桶字段, 分桶个数
每一个桶的数据, 分桶字段.hash%桶的个数;
load方式在进行数据加载的时候,不会进行数据字段的检查的;是无法匹配分桶字段;无法识别任务字段的;

  1. insert ... select ...
insert into table student_buk select * from student_external;

运行日志:
Number of reducers (=3) is more than 1
自动按照分桶个数启动相应个数的reducetask任务;

注意: 分桶字段;string类型,默认算法:分桶字段.hash%桶的个数
分桶字段是数值类型的时候,默认算法:分桶字段%分桶个数

posted @ 2019-05-15 17:03  耳_东  阅读(116)  评论(0)    收藏  举报