分区表的特点/好处:需要产生分区目录,查询的时候使用分区字段筛选数据,避免全表扫描从而提升查询效率
效率上注意:如果分区表,在查询数据的时候没有使用分区字段去筛选数据,效率不变。
分区字段名注意:分区字段名不饿呢个和原有字段名重复,因为分区字段名要作为字段拼接到表后
创建分区表: create [external] table [if not exists] 表名(字段名 字段类型 , 字段名 字段类型 , ... )partitioned by (分区字段名 分区字段类型)... ;
自动生成分区目录并插入数据: load data [local] inpath '文件路径' into table 分区表名 partition (分区字段名='值');
注意: 如果加local后面文件路径应该是linux本地路径,如果没有加那么就是hdfs文件路径
-- 创建库使用库
create database hive3;
use hive3;
-- 演示分区表
-- 1.一级分区表
-- 建表
create table one_part_order(
oid string,
name string,
price double,
num int
)partitioned by (year string)
row format delimited
fields terminated by ' ';
-- 加载数据
-- 先在hdfs的source目录下准备好订单相关数据文件
-- 使用load加载数据到分区表中
load data inpath '/source/order202251.txt' into table one_part_order partition (year=2022);
load data inpath '/source/order2023415.txt' into table one_part_order partition (year='2023');
load data inpath '/source/order202351.txt' into table one_part_order partition (year='2023');
load data inpath '/source/order202352.txt' into table one_part_order partition (year='2023');
-- 验证数据
select * from one_part_order limit 20;
/*分区表特点
去hdfs验证分区表的本质就是分目录存储各个小文件
通过查询发现分区字段最终效果作为一个字段拼接到表最后
*/
-- 分区表的好处:避免全表扫描,提升查询效率
select * from one_part_order where year='2022';
-- 注意: 如果查询的时候条件不是分区字段,效率不会改变
select * from one_part_order where price=20;
创建分区表: create [external] table [if not exists] 表名(字段名 字段类型 , 字段名 字段类型 , ... )partitioned by (一级分区字段名 分区字段类型, 二级分区字段名 分区字段类型 , ...) ;
自动生成分区目录并插入数据: load data [local] inpath '文件路径' into table 分区表名 partition (一级分区字段名='值',二级分区字段名='值' , ...);
注意: 如果加local后面文件路径应该是linux本地路径,如果没有加那么就是hdfs文件路径
-- 2.多级分区表
-- 创建表
create table multi_part_order(
oid string,
name string,
price float,
num int
)partitioned by (year string,month string,day string)
row format delimited
fields terminated by ' ';
-- 加载数据
-- 思考数据文件在哪里?如果想从hdfs加载,怎么操作?上传到hdfs指定位置
load data inpath '/source/order202251.txt' into table multi_part_order partition (year=2022,month=05,day=01);
load data inpath '/source/order202351.txt' into table multi_part_order partition (year=2023,month=05,day=01);
load data inpath '/source/order202352.txt' into table multi_part_order partition (year=2023,month=05,day=02);
load data inpath '/source/order2023415.txt' into table multi_part_order partition (year=2023,month=04,day=15);
-- 验证数据
select * from multi_part_order;
-- 分区表的好处:避免全表扫描,提升查询效率
-- 需求: 统计2023年商品总销售额
select sum(price*num) from multi_part_order where year='2023'; -- 提升效率
-- 需求: 统计2023年5月份商品总销售额
select sum(price*num) from multi_part_order where year='2023'and month='5'; -- 提升效率
-- 需求: 统计2023年5月1日的商品总销售额
select sum(price*num) from multi_part_order where year='2023'and month='5' and day='1'; -- 提升效率
添加分区: alter table 分区表名 add partition (分区字段名='值' , ...);
删除分区: alter table 分区表名 drop partition (分区字段名='值' , ...);
修改分区名: alter table 分区表名 partition (分区字段名='旧值' , ...) rename to partition (分区字段名='新值' , ...);
查看所有分区: show partitons 分区表名;
同步/修复分区: msck repair table 分区表名;
-- 分区操作
-- 注意: 先确定有一级分区和多级分区表,如果没有先创建再做分区操作
select * from one_part_order limit 20;
select * from multi_part_order limit 20;
-- 添加分区(本质在hdfs上创建分区目录)
alter table one_part_order add partition (year=2024);
alter table multi_part_order add partition (year=2024,month=5,day=1);
-- 修改分区(本质在hdfs上修改分区目录名)
alter table one_part_order partition (year=2024) rename to partition (year=2030);
alter table multi_part_order partition (year=2024,month=5,day=1) rename to partition (year=2030,month=6,day=10);
-- 查看所有分区
show partitions one_part_order;
show partitions multi_part_order;
-- 删除分区
alter table multi_part_order drop partition (year=2030,month=6,day=10);
alter table multi_part_order drop partition (year=2023,month=5,day=2);
alter table multi_part_order drop partition (year=2023,month=5);
alter table multi_part_order drop partition (year=2023,month=4);
alter table multi_part_order drop partition (year=2022);
-- 如果在hdfs上创建符合分区目录格式的文件夹,可以使用msck repair修复
-- 举例:手动创建一个year=2033目录
msck repair table one_part_order;
msck repair table multi_part_order;
-- 修复后再次查看所有分区
show partitions one_part_order;
show partitions multi_part_order;
hive文档: https://cwiki.apache.org/confluence/display/Hive/Configuration+Properties
hdfs文档: https://hadoop.apache.org/docs/stable/hadoop-project-dist/hadoop-hdfs/hdfs-default.xml
yarn文档: https://hadoop.apache.org/docs/stable/hadoop-yarn/hadoop-yarn-common/yarn-default.xml
mr文档: https://hadoop.apache.org/docs/stable/hadoop-mapreduce-client/hadoop-mapreduce-client-core/mapred-default.xml
分桶表特点/好处: 需要产生分桶文件, 查询的时候特定操作上提升效率(过滤,join,分组 以及 抽样)
效率上注意: 如果分桶表,在查询数据的时候没有使用分桶字段去筛选数据,效率不变
分桶字段名注意: 分桶字段名必须是原有字段名, 因为分桶需要根据对应字段值取余数把余数相同的数据放到同一个分桶文件中
-- 默认开启,hive2.x版本已经被移除
set hive.enforce.bucketing; -- 查看未定义因为已经被移除
set hive.enforce.bucketing=true; -- 修改
-- 查看reduce数量
-- 参数优先级: set方式 > hive文档 > hadoop文档
set mapreduce.job.reduces; -- 查看默认-1,代表自动根据桶数量匹配reduce数量
set mapreduce.job.reduces=3; -- 设置参数
创建基础分桶表:
create [external] table [if not exists] 表名(
字段名 字段类型
)
clustered by (分桶字段名)
into 桶数量 buckets ;
-- 1.创建基础分桶表,要求分3个桶
create table course_base (
cid int,
cname string,
sname string
)
clustered by(cid) into 3 buckets
row format delimited fields terminated by '\t';
-- 2.load方式加载数据
-- 前提: 已经上传course.txt文件到hdfs的/source目录下
load data inpath '/source/course.txt' into table course_base;
-- 3.查询数据,观察结果
select * from course_base;
创建基础分桶表,然后桶内排序:
create [external] table [if not exists] 表名(
字段名 字段类型
)
clustered by (分桶字段名)
sorted by(排序字段名 asc|desc) # 注意:asc升序(默认) desc降序
into 桶数量 buckets ;
-- 1.创建基础分桶表,要求分3个桶,桶内根据cid降序
create table course_sort (
cid int,
cname string,
sname string
)
clustered by(cid) sorted by (cid desc) into 3 buckets
row format delimited fields terminated by '\t';
-- 2.加载数据
-- 还是使用/source/course.txt数据文件
load data inpath '/source/course.txt' into table course_sort;
-- 3.查询数据,观察结果
select * from course_sort;
已知课程表course.txt数据文件,要求建表,根据sname分桶,然后桶内再根据cid升序排序,观察结果
数据倾斜问题: 分桶字段值如果大量重复,相同的会分到同一个桶内,导致数据倾斜
-- 1.创建基础分桶表,要求分3个桶,桶内根据cid降序
create table course_test (
cid int,
cname string,
sname string
)
clustered by(sname) sorted by (cid) into 3 buckets
row format delimited fields terminated by '\t';
-- 2.加载数据
-- 还是使用/source/course.txt数据文件
load data inpath '/source/course.txt' into table course_test;
-- 3.查询数据,观察结果
select * from course_test;
分桶原理:
如果是数值类型分桶字段: 直接使用数值对桶数量取模
如果是字符串类型分桶字段: 底层会使用hash算法计算出一个数字然后再对桶数量取模
Hash: Hash是一种数据加密算法,其原理我们不去详细讨论,我们只需要知道其主要特征:同样的值被Hash加密后的结果是一致的
举例: 字符串“binzi”被Hash后的结果是93742710(仅作为示意),那么无论计算多少次,字符串“binzi”的结果都会是93742710。
计算余数: hash('binzi')%3==0
注意: 同样的数据得到的结果一致,如’binzi’ hash取模结果是0,无论计算多少次,它的取模结果都是0
分区表
创建表的时候使用关键字: partition by (分区字段名 分区字段类型)
分区字段名注意事项: 是一个新的字段,需要指定类型,且不能和其他字段重名
分区表好处: 使用分区字段作为条件的时候,底层直接找到对应的分区目录,能够避免全表扫描,提升查询效率
分区表最直接的效果: 在hfds表目录下,分成多个分区目录(year=xxxx,month=xx,day=xx)
不建议直接上传文件在hdfs表根路径下: 分区表直接不能识别对应文件中数据,因为分区表会找分区目录下的数据文件
使用load方式加载hdfs中文件: 本质是移动文件到对应分区目录下
分桶表
创建表的时候使用关键字: clustered by (分桶字段名) into 桶数量 buckets
分桶字段名注意事项: 是指定一个已存在的字段,不需要指定类型
分桶表好处: 使用分桶字段做抽样等特定操作的时候,也能提升性能效率
分桶表最直接的效果: 在hdfs表目录或者分区目录下,分成多个分桶文件(000000_0,000001_0,000002_0...)
不建议直接上传文件在hdfs表根路径下: 分桶表可以识别对应文件中数据,但是并没有分桶效果,也是不建议的
使用load方式加载hdfs中文件: 本质是复制数据到各个分桶文件中
其中ROW FORMAT是语法关键字,DELIMITED和SERDE二选其一。本次我们主要学习DELIMITED关键字相关知识点
如果使用delimited: 表示底层默认使用的Serde类:LazySimpleSerDe类来处理数据。
如果使用serde:表示指定其他的Serde类来处理数据,支持用户自定义SerDe类。
Hive默认的序列化类: LazySimpleSerDe
包含4种子语法,分别用于指定字段之间、集合元素之间、map映射 kv之间、换行的分隔符号。
在建表的时候可以根据数据的类型特点灵活搭配使用。
COLLECTION ITEMS TERMINATED BY '分隔符' : 指定集合类型(array)/结构类型(struct)元素的分隔符
MAP KEYS TERMINATED BY '分隔符' : 表示映射类型(map)键值对之间用的分隔
复杂类型建表格式:
...
[row format delimited] # hive的serde机制
[fields terminated by '字段分隔符'] # 自定义字段分隔符固定格式
[collection ITEMS terminated by '集合分隔符'] # 自定义array同类型集合和struct不同类型集合
[map KEYS terminated by '键值对分隔符'] # 自定义map映射kv类型
[lines terminated by '\n'] # # 默认即可
...;
hive复杂类型: array struct map
array类型: 又叫数组类型,存储同类型的单数据的集合
建表指定类型: array<数据类型>
取值: 字段名[索引] 注意: 索引从0开始
获取长度: size(字段名)
判断是否包含某个数据: array_contains(字段名,某数据)
struct类型: 又叫结构类型,可以存储不同类型单数据的集合
建表指定类型: struct<子字段名1:数据类型1, 子字段名2:数据类型2 , ...>
取值: 字段名.子字段名n
map类型: 又叫映射类型,存储键值对数据的映射(根据key找value)
建表指定类型: map
取值: 字段名[key]
获取长度: size(字段名)
获取所有key: map_keys()
获取所有value: map_values()
需求: 已知data_for_array_type.txt文件,存储了学生以及居住过的城市信息,要求建hive表把对应的数据存储起来
-- 演示使用简单类型映射数据
-- 创建表
create table test_array1(
name string,
location string
)row format delimited
fields terminated by '\t';
-- 加载数据
load data inpath '/source/data_for_array_type.txt' into table test_array1;
-- 验证数据
select * from test_array1;
-- 演示使用array类型映射数据
-- 创建表
create table test_array2(
name string,
location array<string>
)row format delimited
fields terminated by '\t'
collection items terminated by ',';
-- 加载数据
load data inpath '/source/data_for_array_type.txt' into table test_array2;
-- 验证数据
select * from test_array2;
-- 需求: 查询zhangsan的地址有几个?
select size(location) from test_array2 where name = 'zhangsan';
-- 需求: 查询zhangsan的第二个地址?
select location[1] from test_array2 where name = 'zhangsan';
-- 需求: 查询zhangsan是否在tianjin住过?
select array_contains(location,'tianjin') from test_array2 where name = 'zhangsan';
需求: 已知data_for_struct_type.txt文件存储了用户姓名和年龄基本信息,要求建hive表把对应的数据存储起来
-- 演示使用简单类型映射数据
-- 创建表
create table test_struct1(
id int,
info string
)row format delimited
fields terminated by '#';
-- 加载数据(前提hdfs必须有对应文件)
load data inpath '/source/data_for_struct_type.txt' into table test_struct1;
-- 验证数据
select * from test_struct1;
-- 演示struct类型映射数据
-- 创建表
create table test_struct2(
id int,
info struct<name:string,age:int>
)row format delimited
fields terminated by '#'
collection items terminated by ':';
-- 加载数据(前提hdfs必须有对应文件)
load data inpath '/source/data_for_struct_type.txt' into table test_struct2;
-- 验证数据
select * from test_struct2;
-- 需求: 获取所有的姓名
select info.name from test_struct2;
-- 需求: 获取所有的年龄
select info.age from test_struct2;
需求: 已知data_for_map_type.txt文件存储了每个学生详细的家庭信息,要求建hive表把对应数据存储起来
-- 演示简单类型映射数据
-- 创建表
create table test_map1(
id int,
name string,
info string,
age int
)row format delimited
fields terminated by ',';
-- 加载数据(前提hdfs有对应数据文件)
load data inpath '/source/data_for_map_type.txt' into table test_map1;
-- 验证数据
select * from test_map1;
-- 演示map类型的应用
-- 创建表
create table test_map2(
id int,
name string,
info map<string,string>,
age int
)row format delimited
fields terminated by ','
collection items terminated by '#'
map keys terminated by ':';
-- 加载数据(前提hdfs有对应数据文件)
load data inpath '/source/data_for_map_type.txt' into table test_map2;
-- 验证数据
select * from test_map2;
-- 需求: 查看所有人的father,mother信息
select name,info['father'] as father ,info['mother'] as mother from test_map2;
-- 需求: 查看所有人的家庭相关角色
select name,map_keys(info) from test_map2;
-- 需求: 查看所有人的家庭相关姓名
select name,map_values(info) from test_map2;
-- 需求: 查看所有人的家庭相关人员个数
select name,size(info) as cnt from test_map2;
-- 需求: 查看马大云是否包含brother角色
select name,array_contains(map_keys(info),'brother') from test_map2 where name = '马大云';
-- 创建订单表
CREATE TABLE orders (
orderId bigint COMMENT '订单id',
orderNo string COMMENT '订单编号',
shopId bigint COMMENT '门店id',
userId bigint COMMENT '用户id',
orderStatus tinyint COMMENT '订单状态 -3:用户拒收 -2:未付款的订单 -1:用户取消 0:待发货 1:配送中 2:用户确认收货',
goodsMoney double COMMENT '商品金额',
deliverMoney double COMMENT '运费',
totalMoney double COMMENT '订单金额(包括运费)',
realTotalMoney double COMMENT '实际订单金额(折扣后金额)',
payType tinyint COMMENT '支付方式,0:未知;1:支付宝,2:微信;3、现金;4、其他',
isPay tinyint COMMENT '是否支付 0:未支付 1:已支付',
userName string COMMENT '收件人姓名',
userAddress string COMMENT '收件人地址',
userPhone string COMMENT '收件人电话',
createTime timestamp COMMENT '下单时间',
payTime timestamp COMMENT '支付时间',
totalPayFee int COMMENT '总支付金额'
) ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t';
-- 加载数据(因为是普通内部表可以直接上传文件到hfds表路径下)
-- 1.演示基础查询
-- 查询数据(*默认就是所有字段)
select * from orders;
-- 指定字段查询
select orderId,totalMoney from orders;
-- 指定字段并且取别名查询
select orderId as bh,totalMoney as zj from orders;
-- 当然也可以给表起别名(目前单表即使起了也没有多大意义)
select o.orderId ,o.totalMoney from orders o;
-- 查询支付类型要求去重
select distinct payType from orders;
-- 2.演示where条件查询
/* 比较运算符: > < >= <= != <>
逻辑运算符: and or not
模糊查询: %任意0个或者多个 _任意1个
空判断: 为空is null 不为空is not null
范围查询: 连续范围between x and y 非连续范围 in(x,y,z)
*/
-- 查询广东省订单
select * from orders where userAddress like '广东省%';
-- 3.演示聚合查询
-- 查询广东省数据量
select count(*) from orders where userAddress like '广东省%';
-- 4.演示分组查询
-- 统计已支付和未支付各自多少人
select isPay,count(*) from orders group by isPay;
-- 5.演示条件查询,聚合查询,分组查询综合练习
-- 注意: select后的字段要么在groupby后出现要么在聚合函数内出现,否则报错
-- 在已支付订单中,统计每个用户最高的一笔消费金额
select userid,max(totalMoney) from orders where isPay=1 group by userid;
-- 统计每个用户的平均消费金额
select userid,avg(totalMoney) from orders group by userid;
-- 统计每个用户的平均消费金额并且筛选大于10000的
select userid,avg(totalMoney) from orders group by userid having avg(totalMoney) >10000 ;
-- 统计每个用户的平均消费金额并且筛选大于10000的,平均值要求保留2位小数
select userid,round(avg(totalMoney),2) from orders group by userid having avg(totalMoney) >10000 ;
-- 6.演示排序查询
-- asc默认升序 desc 降序
-- 查询广东省订单,要求按照总价降序排序
select orderId,totalMoney from orders where userAddress like '广东省%' order by totalMoney desc;
-- 7.演示分页查询
-- limit x,y 注意: x和y都是整数,x是从0开始起始索引,y是查询的条数
-- 查询广东省订单总价最高的前5个订单
select orderId,totalMoney from orders where userAddress like '广东省%' order by totalMoney desc limit 5;
-- 演示多表join操作
-- 创建用户表
CREATE TABLE users (
userId int,
loginName string,
loginSecret int,
loginPwd string,
userSex tinyint,
userName string,
trueName string,
brithday date,
userPhoto string,
userQQ string,
userPhone string,
userScore int,
userTotalScore int,
userFrom tinyint,
userMoney double,
lockMoney double,
createTime timestamp,
payPwd string,
rechargeMoney double
) ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t';
-- 交叉连接(cross join)本质是一个美丽错误,也有美丽的名称叫笛卡尔积
select * from users cross join orders; -- 显式
select * from users , orders; -- 隐式
-- 内连接(左表 inner join 右表 on 条件) 本质取两个表的交集
select * from users inner join orders o on users.userId = o.userId;
-- 左外连接(左表 left outer join 右表 on 条件) 本质取两个表的差集
select * from users left outer join orders o on users.userId = o.userId;
-- 右外连接(左表 right outer join 右表 on 条件) 本质取两个表的差集
select * from users right outer join orders o on users.userId = o.userId;
-- 子查询(一个select 语句作为另外一个select语句的表或者条件)
-- 查询最高订单金额对应的用户id
select userId from orders where totalMoney=(select max(totalMoney) from orders);
-- 当然还有自连接: 自连接应用场景比较局限主要是省市区区域表或者员工以及领导工号表
SELECT [ALL | DISTINCT] 字段名 , 字段名 , ...
FROM 表名
[WHERE 非聚合条件]
[GROUP BY 分组字段名]
[HAVING 聚合条件]
[ORDER BY 排序字段名]
[CLUSTER BY 分桶排序字段名 | [DISTRIBUTE BY 分桶字段名] [SORT BY 排序字段名]]
[LIMIT number]
在Hive中除了支持cross join(交叉连接,也叫做笛卡尔积),inner join(内连接)、left outer join(左外连接)、right outer join(右外连接)还支持full outer join(全外连接)、left semi join(左半开连接)
全外连接: 左表 full outer join 右表 on 条件
左半开连接: 左表 left semi join 右表 on 条件
-- hive不同于mysql的join操作
-- 全外连接(左表 full outer join 右表 on 条件) 大白话就是左外和右外结果合并
select * from users u full outer join orders o on u.userId = o.userId;
-- 左半开连接(左表 left semi join 右表 on 条件)
select * from users u left semi join orders o on u.userId = o.userId;
set mapreduce.job.reduces: 查看当前设置的reduce数量 默认结果是-1,代表自动匹配reduce数量和桶数量一致
set mapreduce.job.reduces = 3 : -- 修改reduces数量
cluster by 字段名: 分桶且正序排序 弊端: 分和排序是同一个字段,相对不灵活
distribute by 字段名 sort by 字段名: distribute by负责分,sort by负责排序, 相对比较灵活
注意: cluster by 和 distribute by 字段名 sort by 字段名 受当前设置的reduces数量影响,但是设置的reduces数量对order by无影响,因为orderby就是全局排序,就是一个reduce
-- 演示hive其他排序操作
-- 创建基础表主要用于给分桶表准备数据
create table students
(
id int,
name string,
gender string,
age int,
class string
)
row format delimited
fields terminated by ',';
-- 创建基础表后,上传students.txt文件
-- 设置reduce数量,注意:此种方式num默认是-1,代表自动匹配reduce数量和桶数量一致
set mapreduce.job.reduces; -- 查看当前设置的reduce数量 默认结果是-1
set mapreduce.job.reduces = 3; -- 默认修改的reduces数量也可以理解成是桶的数量
-- 1.cluster by 分桶且正序排序 弊端: 分和排序是同一个字段,相对不灵活
-- 需求: 根据class分组且按照class正序排序
select * from students cluster by class;
-- 2.distribute by class sort by id
-- 需求: 根据gender分组并且按照id降序排序
select * from students distribute by gender sort by id desc;
-- 注意: order by是全局排序,设置的reduces数量对order by无影响,默认就是一个reduce
select * from students order by id desc;
sql模糊查询关键字: like 任意0个或者多个: % 任意1个: _
正则模糊查询关键字: rlike 任意0个或者多个: .* 任意1个: . 正则语法还有很多...
-- 查找广东省的数据
select * from orders where userAddress like '广东省%';
select * from orders where userAddress rlike '广东省.*';
-- 查找用户地址是:xx省 xx市 xx区的数据
select * from orders where userAddress like '__省 __市 __县';
select * from orders where userAddress rlike '..省 ..市 ..县';
-- 查找用户姓为张、王、邓
select * from orders where userName like '张%' or userName like '王%' or userName like '邓%';
select * from orders where userName rlike '张.*' or userName rlike '王.*' or userName rlike '邓.*';
select * from orders where userName rlike '[张王邓].*';
-- 查找手机号符合:188****0*** 规则
select * from orders where userPhone like '188____0___'; -- 如果是188abcd0中国牛都能匹配成功
select * from orders where userPhone rlike '188....0...'; -- 如果是188abcd0中国牛都能匹配成功
select * from orders where userPhone rlike '188\\S{4}0\\d{3}'; -- \S 非空白 \d: 数字
select * from orders where userPhone rlike '188\\W{4}0\\d{3}'; -- \W 特殊字符 \d: 数字
union联合查询: 就是把两个select语句结果合并成一个临时结果集,整体可以用于其他sql操作
union [distinct]: 去重,只是省略了distinct
union all : 不去重
-- 演示uninon联合操作
-- 注意: 个数和顺序以及类型都要一致
select id,cname,sname from course_bucket where sname = '王力鸿'
union
select id,sname,cname from course_bucket where sname = '林均街';
-- 注意: union单独使用默认distinct去重
select id,cname,sname from course_bucket
union
select id,cname,sname from course_bucket;
-- 注意: union all不去重展示所有
select id,cname,sname from course_bucket
union all
select id,cname,sname from course_bucket;
TABLESAMPLE抽样好处: 尽可能实现随机抽样,并且不走MR查询效率相对较快
基于随机分桶抽样格式: SELECT 字段名 FROM tbl TABLESAMPLE(BUCKET x OUT OF y ON(字段名 | rand()))
y:表示将表数据随机划分成y份(y个桶)
x:表示从y里面随机抽取x份数据作为取样
| : 或者
字段名: 表示随机的依据基于某个列的值
rand(): 表示随机的依据基于整行
-- 演示抽样查询
-- 需求: 从orders表中抽样部分数据
-- 方式1: 根据分桶字段id
SELECT orderid,totalMoney FROM orders TABLESAMPLE(BUCKET 1 OUT OF 5 ON orderid);
-- 方式2: 使用随机函数
SELECT orderid,totalMoney FROM orders TABLESAMPLE(BUCKET 1 OUT OF 5 ON rand());
虚拟列是Hive内置的可以在查询语句中使用的特殊标记,可以查询数据本身的详细参数。
Hive目前可用3个虚拟列:
INPUT__FILE__NAME:显示数据行所在的具体文件
BLOCK__OFFSET__INSIDE__FILE:显示数据行所在文件的偏移量
ROW__OFFSET__INSIDE__BLOCK:显示数据所在HDFS块的偏移量 注意: 此虚拟列需要设置:SET hive.exec.rowoffset=true 才可使用
-- 演示内置虚拟列
-- 打开ROW__OFFSET__INSIDE__BLOCK
SET hive.exec.rowoffset=true;
-- 演示查询
SELECT *, INPUT__FILE__NAME, BLOCK__OFFSET__INSIDE__FILE, ROW__OFFSET__INSIDE__BLOCK FROM course_bucket;