Hive Day02
课程回顾
yarn的产生背景
hadoop1.0 mapreduce存在严重的缺陷
- 扩展性不足
- 资源利用率低
- 存在单点故障
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
非分区表的一个表的所有数据读存储在上面的表的对应目录下
非分区表中,一个表对应一个目录;
分区表的表现形式
分区表:
将表中的数据分别存储在不同的区域下;将表中的不同区的数据分别存储在不同的目录下;
分区表一般指定一个分区字段;分区字段选择的依据是查询的过滤字段
比如:学生信息表,查询的时候通常按照班级进行查询;分区字段就是班级;
分区表这里一个分区就会对应一个目录结构;
我们在查询的过程中,按照分区字段进行过滤查询;这个时候只会扫描指定分区字段值的目录;
分区表总结:
- 分区表对应的不同的目录结构
- 减少查询的时候的数据扫描范围;提升查询性能;
分桶表(类似mapreduce的分区的概念)
作用:
- 提升抽样的性能
- 提升join的性能
目录划分:
将不同的桶的数据进行分别存储在不同的文件中;
分桶表来说:选择一个分桶字段(相当于mapreduce中的分区字段)
选择完成分桶字段之后,指定桶的个数(分区个数/reducetask的个数)
分桶的数据划分:分桶字段.hash%分桶个数;
余数为0----桶0
余数为1----桶1
最后的数据目录:
数据量比较大的时候;先进行数据抽样分析;抽取样本数据进行测试;
样本数据的要求;具有代表性;抽取的数据要足够散列;桶数据就是这样的数据;可以直接拿一个桶的数据作为样本数据;
视图
主要为了提升hql语句的可读性;
- hive中的视图只存在逻辑视图,不存在物化视图
逻辑视图:只存储视图代表的hql语句,不会进行执行;
物化视图:将视图对应的查询语句执行出来结果; - hive的视图仅仅是相当于一条查询语句的快捷方式;
- hive中的视图,在查询视图的时候才会真正的执行;
- 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>
元数据的结构:
-
hive中的数据库的描述信息
DBS表存储的是hive的数据库的描述信息
原始数据的hdfs的存储目录
每当hive中创建一个数据库的时候,这个表中就会添加一条数据; -
hive中的表的描述信息的元数据;TBLS
每当hive中创建一个表,这个表中就会添加一条数据;
所属库id 表明 表类型 -
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 exists和if 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]
说明:
-
EXTERNAL 关键字;加上这个关键字,建的表是外部表;不加这个关键字;建的表就是内部表;
-
IF NOT EXISTS 防止报异常的
-
Comment 指定列或表的描述信息
-
PARTITIONED BY (col_name data_type [COMMENT col_comment], ...) 指定分区字段,
PARTITIONED BY (分区字段名 分字段类型 Comment 分区字段的描述信息)
注意: 分区字段一定不能在建表字段中 -
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 指定桶的个数 -
ROW FORMAT row_format 指定分隔符
fields terminated by 列分隔符
lines terminated by 行分隔符
map keys terminated by map集合的key和vlaue的分隔符 -
STORED AS file_format 指定原始数据的存储格式
textfile 文本格式 默认的方式
rcfile 行列格式 在行的方向上切分数据存储的块;保证一行在一个数据块中
sequencefile 二进制存储格式 -
LOCATION hdfs_path 指定原始数据的存储位置;这里没有指定,则读取配置文件中的;如果制定了则覆盖配置文件中的;
一定是hdfs上的路径
hive的原始数据的存储的配置:
hive-default.xmlhive-site.xml- 建表语句中的
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);
增加列的时候一定要添加数据类型
修改列
-
修改列名
alter table t_name change oldname newname type; alter table student_copy change content text string; -
修改列类型
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);
修改分区的存储位置
分区的默认存储位置:是在表的目录下创建的分区目录;
我们可以手动指定某一个分区的存储位置
-
添加的分区时候进行指定
alter table student_ptn add partition(grade=1308) location '/user/student/1308'; -
对于已经添加的分区修改存储位置;添加数据的时候才会生效,不会立即生效;
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;
默认分区字段都在最后的;
注意:动态分区中,必须将分区字段放在查询语句的最后;
原因:分区表中会自动将分区字段放在表的普通字段的后面;
动态分区和静态分区的区别
- 静态分区 分区手动指定的
动态分区的分区根据数据自动生成的 - 静态分区可能存在某一个分区为空的情况
动态分区每一个分区中至少都有一条数据的;不存在空分区的可能; - 动态分区比较消耗性能;动态分区中如果设置,reducetask的个数;针对的是每一个动态分区都有效的;set reducetasks=3;每一个分区中的数据都会启动3个reducetask;在动态分区中一定要慎重使用reducetask的个数
多级分区
分区字段找过一个分区叫做多级分区;多级分区之间必然存在从属关系;
partition(name,age)
name称为高级分区,一级分区
age 二级分区
分区的时候,现根据高级分区,再根据低级分区
创建一个多级分区表
分区字段:过滤条件
输入写入:
-
两个分区都是静态的
alter table sudent_ptn01 add partition(grade=1303,yuwen='34'); -
只有一个是静态分区;另外一个是动态分区;
这个静态分区只能是高级分区;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;
- 全部动态
insert into table student_ptn01 partition(grade,yuwen) select stu_id,name,shuxue,yingyu,grade,yuwen from student_external;
先查询一级分区,在查询二级分区;
分桶表的数据插入
- load方式:不支持
load data local inpath "" into table student_buk;
分桶字段, 分桶个数
每一个桶的数据, 分桶字段.hash%桶的个数;
load方式在进行数据加载的时候,不会进行数据字段的检查的;是无法匹配分桶字段;无法识别任务字段的;
insert ... select ...
insert into table student_buk select * from student_external;
运行日志:
Number of reducers (=3) is more than 1
自动按照分桶个数启动相应个数的reducetask任务;
注意: 分桶字段;string类型,默认算法:分桶字段.hash%桶的个数
分桶字段是数值类型的时候,默认算法:分桶字段%分桶个数


浙公网安备 33010602011771号