分区表
单分区表
--单分区表
--创建分区表
--创建分区表格式 create table 表名(字段1 字段类型,字段2 字段类型)partitioned by(分区字段 字段类型)
--分区表中,分区字段也会出现在虚拟表中,此时该字段的字段名称,不能与其他实体字段冲突
create table test_db.score_part(
s_sname string,
s_score string,
score int
)
partitioned by (month string)
row format delimited fields terminated by '\t';
--2、查看表结构后
desc formatted test_db.score_part;
--3、给分区表加载数据
load data local inpath '/root/hive_data/score.txt' into table test_db.score_part;
--4、查看表中加载的数据内容
select * from test_db.score_part;
--经观察发现,如果不书写分区名称,则加载到默认分区中
--5、使用put 将数据上传至表目录中
hadoop fs -put /root/hive_data/score.txt /user/hive/warehouse/test_db.db.score_part;
select * from test_db.score_part;
--经过查询,我们发现没有映射出新的数据,在表目录中添加数据文件,也不能映射成功
--6、指定分区名称加载数据
--我们在加载数据时指定分区名称,则在该表目录会创建一个分区目录,将数据加载进去
load data local inpath '/root/hive_data/score.txt' into table test_db.score_part partition (month='2022-12');
select * from test_db.score_part;
load data local inpath '/root/hive_data/score.txt' into table test_db.score_part partition (month='2020-10');
select * from test_db.score_part;
--经观察发现,只有写入到分区目录中的文件才会被映射成功,否则映射失败
多级分区表
--多级分区表
--1、创建一个多级分区表
create table test_db.score_parts
(
s_name string,
s_course string,
score int
)
partitioned by (year string,month string,day string)
row format delimited fields terminated by '/t';
--和普通分区表相比,多级分区表就是在普通分区表的基础上增加几个键 = 值即可
--2、给多级分区表记载数据
load data local inpath '/root/hive_data/score.txt' into table test_db.score_parts
partition (year ='2022',month='03',day='05');
load data local inpath '/root/hive_data/score.txt' into table test_db.score_parts
partition (year ='2022',month='06',day='05');
load data local inpath '/root/hive_data/score.txt' into table test_db.score_parts
partition (year ='2022',month='06',day='15');
--3、查询使用该方法插入的数据打印结果是什么
select * from test_db.score_parts;
--4、查看分区
show partitions test_db.score_parts;
--5、删除分区
alter table test_db.score_parts drop partition (year='2022',month='03',day='05');
--6、修改分区名称
alter table test_db.score_parts partition (year ='2022',month='06',day='15')
rename to partition (year ='2022',month='06',day='4');
注意:
1、formatted可以看到分区字段的字段内容
2、多级分区会在服务中产生多个层级的表目录结构
3、多级分区表之间必须要有层级从属关系,比如年,月,日,省,市,区等
4、多级分区表的层级一般步骤过三级,因为数据层级过多,就会产生大量的小文件
思考:为什么要对表进行分区?
我们再查询数据内容时,如果对表进行了分区,并且根据分区字段进行了筛选则我们读取文件时只读取对应分区内的数据条目,减少了数据检索方位,提高了执行效率
分桶表
--分桶表
--1、创建一个分桶表
--格式:create table 表名(字段1 字段类型 ,字段2 字段类型....)clustered by(分桶字段)into 分桶数 buckets
create table test_db.course_buck(
c_id string,
c_name string,
t_id string
)
clustered by (c_id)into 3 buckets row format delimited fields terminated by '\t';
--2、查看分区表中详细的信息
desc formatted test_db.course_buck;
--3、想分桶表中插入数据
--方式一、直接load data
--在Hive早期版本中这种插入方式无效
load data local inpath '/root/hive_data/course.txt' into table test_db.course_buck;
--查看加载结果
select * from test_db.course_buck;
--方式二:间接加载
--步骤1:创建一个未分桶的临时表,将数据全部加载进来
create table test_db.course(
c_id string,
c_name string,
t_id string
)
row format delimited fields terminated by '\t';
--步骤2:使用load data给临时表加载数据
load data local inpath '/root/hive_data/course.txt' into table test_db.course;
--步骤3:查看临时表中的数据是否完全
select * from test_db.course;
--步骤4:复制一个course_buck的表结构
create table test_db.course_buck1 like test_db.course_buck;
--步骤5:读取临时表中的数据insert into插入到分桶表中
insert into test_db.course_buck1 select * from test_db.course;
--步骤6:查询插入后分桶表中的数据
select * from course_buck1;
分桶依据:哈希取模法
哈希:散列函数,这种函数能使用任意一个变量都能计算出一个唯一值,该值为数字
例如:"你好世界’ 这个字符串就可以计算出一个哈希值2345678
我们会根据这个哈希值的数值除以桶数计算出一个余数这种方法叫做取余或者取模
根据取模规律,我们可以按照余数的不同将数据拆分至不同的桶内
思考:分桶时有没有可能出现空桶?
有,例如:我们按照学生性别分桶分为三个桶,必然有一个是空桶
思考:分桶时有没有可能出现数据分布极其不均匀?
有,比如统计班里男女信息,按照性别分桶,分为两桶,男女分布不均
在开发中,我们要极力避免上述两种情况出现
对比分区表和分桶表的优势
分区表:
1、可以提高表的查询效率(分区后减少了数据扫描的范围)
2、分区表可以将表以多级目录的形式展示,逻辑更加清晰
注意:如果我们想让分区表的查询效率提升,我们要根据分区字段进行筛选,如果不使用分区表筛选,和普通表无异
举例:select * from 表名 where 分区字段=分区值;
分桶表:
1、提高查询效率(分桶后可以根据哈希取模的值缩小数据检索范围)
2、提高了group by分组效率(在分桶时相同的数据已经存放在了同一个分桶文件中)
3、降低了join连接笛卡尔积数量,提升连接效率
笛卡尔积
左表和右表相连接,我们如果不分组就要进行左表记录 * 右表记录的连接次数,这种最大连接此时就是笛卡尔积
4、提高随机抽样效率
注意:只有按照分桶字段进行筛选,分组和连接才会提高查询效率,否则和普通表无异。
分区表和分桶表有哪些不同?
1、分区表使用的分区字段是元数据字段,分桶表使用的字段是实体字段
2、分区表是将数据拆分为不用的目录存放,分桶表是将数据拆分为不同的文件存放
3、分区表主要是为了提高查询效率,降低检索范围,分桶表主要是提高连接效率
分区表和分桶表的相同点
1、无论是分区表还是分桶表,都是对于表的优化手段(可有可无)
2、分区表和分桶表都能在一定程度上提高表查询效率
3、分区表和分桶表必须按照分区,和分桶字段进行操作才可以达到优化的目的
复杂的数据类型
serde机制
serde机制 就是序列化和反序列化机制(文件读写的规则)
它可以指定文件中的字段分隔符,换行符,集合间的分隔符,map间的kv分隔符
默认的序列化机制是LazySimpleSerDe 使用delimited代替
默认的序列化类,可以满足日常工作的百分之九十以上的需求
create table test_db.serde_test(
id int,
name string
)
row format delimited --delimited代表我们使用的是默认的LazySimpleSerDe
fields terminated by '\t' --以\t作为字段见的分隔符
collection items terminated by ';' --代表的是集合间的分隔符
map keys terminated by ';' --map类型 kv之间的分隔符
lines terminated by '\n' --换行符
array数组
1,2,3,4,5在一个字段值中包含多个同类型的数据内容就是数组 该数组包含5个元素,元素间分隔符为逗号
map双列集合
a:1,b:2,c:3在一个字段中,包含多个键值对 该map数据类型中有三个元素,元素间分割符是,kv间的分隔符是:
小米:18在一个字段值中包含多个数据,我们在构建字段类型时,指定这些数据的键,该类型为结构体
array类型数据
--array 类型数据
--1、创建一个表,用来加载array类型数据
create table test_db.array_tb(
name string,
address array<string> --代表array类型数据中存放的是string元素,<tupe>的写法叫做泛型
)
row format delimited --使用默认的序列化方式
fields terminated by '\t' --指定字段间的分隔符为\t
collection items terminated by ',';
--2、向array_tb中导入数据
load data local inpath '/root/hive_data/data_for_array_type.txt' into table test_db.array_tb;
--3、查询表中数据内容
select * from test_db.array_tb;
--4、使用数组类型数据
--需求:查询所有用户和用户去过的第二个城市
select name,address[1] from test_db.array_tb;
--需求:查询所有用户分别去过几个城市
select name,size(address) from test_db.array_tb;
--需求:筛选所有用户中,去过上海的用户
select * from test_db.array_tb where array_contains(address,'shanghai');