目录
一、Hive创建数据库与数据表
1.1.数据库相关操作
1.1.1.创建数据库
1.1.2.创建数据库并指定HDFS存储路径
1.1.3.修改数据库
1.1.4.查看数据库详情信息
1.1.5.删除数据库
1.2.数据表相关操作
1.2.1.创建表语法
1.2.2.管理表(内部表)
1.2.3.外部表
1.2.4.分区表
1.2.5.分桶表
1.2.6.编辑hive表
1.2.7.删除表
1.2.8.表加载数据
1.2.9.表数据导出
1.2.10.清空表数据
二、Hive查询语法
2.1.语法结构
2.2.select
2.2.1.全表查询
2.2.2.选择特定列查询
2.2.3.设置列别名
2.3.limit
2.4.where
2.5.like和rlike
2.6.join
2.6.1.等值join
2.6.2.表的别名
2.6.3.内连接(inner join)
2.6.4.左外连接(left outer join)
2.6.5.右外连接(right outer join)
2.6.6.满外连接(full outer join)
2.6.6.多表连接
2.7.比较运算符(between、in、is null)
2.8.逻辑运算符(and、or、not)
2.9.分组
2.9.1.group by
2.9.2.having
2.10.排序
2.10.1.全局排序(order by)
2.10.2.按照别名排序
2.10.3.多个列排序
2.10.4.每个MapReduce内部排序(sort by)局部排序
2.10.5.分区排序(distribute by)
2.10.6.cluster by
2.11.常用函数
2.11.1.count()
2.11.2.max()
2.11.3.min()
2.11.4.sum()
2.11.5.avg()
语法:
create database if not exists 数据库名;
语法:
create database if not exists 数据库名 location 'HDS存储路径';
示例:
create database if not exists mytestdatabase location '/mytestdatabase';
注意:
hive表的存放模式由hive-site.xml文件中的一个属性指定
hive.metastore.warehouse.dir
/user/hive/warehouse
语法:
alter database 数据库名 set dbproperties('属性键'='属性值');
示例:
##修改数据库的创建日期
alter database mytestdatabase set dbproperties('createtime'='20201120');
注意:
可以使用alter database命令来修改数据库的一些属性,但是数据库的元数据信息不可更改,包括数据库的名称以及数据库所在位置(HDFS存储路径)。
##查看数据库基本信息
desc database 数据库名;
##查看数据库更多详细信息
desc database extended 数据库名;
##删除空数据库(如果数据库下有表执行该命令会报错,需要先删除该数据库下的所有表)
drop database 数据库名;
##删除非空数据库<强制删除数据库>(包含数据库下的表一同删除。危险动作,不要轻易执行!!!)
drop database 数据库名 cascade;
语法:
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、 CREATE TABLE
创建一个指定名字的表。如果相同名字的表已经存在,则抛出异常;用户可以用 IF NOT EXISTS 选项来忽略这个异常。
2、 EXTERNAL
该关键字可以让用户创建一个外部表,在建表的同时指定一个指向实际数据的路径(LOCATION),Hive 创建内部表时,会将数据移动到数据仓库指向的路径;
若创建外部表,仅记录数据所在的路径,不对数据的位置做任何改变。在删除表的时候,内部表的元数据和数据会被一起删除,而外部表只删除元数据,不删除数据。
3、 LIKE
允许用户复制现有的表结构,但是不复制数据。
4、 ROW FORMAT DELIMITED [FIELDS TERMINATED BY char] [COLLECTION ITEMS TERMINATED BY char] [MAP KEYS TERMINATED BY char] [LINES TERMINATED BY char] | SERDE serde_name [WITH SERDEPROPERTIES (property_name=property_value, property_name=property_value, ...)]
用户在建表的时候可以自定义 SerDe 或者使用自带的 SerDe。如果没有指定 ROW FORMAT 或者 ROW FORMAT DELIMITED,将会使用自带的 SerDe。在建表的时候,用户还需要为表指定列,用户在指定表的列的同时也会指定自定义的 SerDe,Hive通过 SerDe 确定表的具体的列的数据。
5、 STORED AS
SEQUENCEFILE|TEXTFILE|RCFILE
如果文件数据是纯文本,可以使用 STORED AS TEXTFILE。如果数据需要压缩,使用 STORED AS SEQUENCEFILE。
6、CLUSTERED BY
对于每一个表(table)或者分区, Hive可以进一步组织成桶,也就是说桶是更为细粒度的数据范围划分。Hive也是 针对某一列进行桶的组织。Hive采用对列值哈希,然后除以桶的个数求余的方式决定该条记录存放在哪个桶当中。
把表(或者分区)组织成桶(Bucket)有两个理由:
(1)获得更高的查询处理效率。桶为表加上了额外的结构,Hive 在处理有些查询时能利用这个结构。具体而言,连接两个在(包含连接列的)相同列上划分了桶的表,可以使用 Map 端连接 (Map-side join)高效的实现。比如JOIN操作。对于JOIN操作两个表有一个相同的列,如果对这两个表都进行了桶操作。那么将保存相同列值的桶进行JOIN操作就可以,可以大大较少JOIN的数据量。
(2)使取样(sampling)更高效。在处理大规模数据集时,在开发和修改查询的阶段,如果能在数据集的一小部分数据上试运行查询,会带来很多方便。
1.2.2.1.Hive建表时的字段类型
分类 | 类型 | 描述 | 字面量示例 |
原始类型 | boolean | true/false | true |
tinyint | 1个字节的有符号整数,-128~127 | 1Y | |
smallint | 2个字节的有符号整数,-32768~32767 | 1S | |
int | 4个字节的带符号整数 | 1 | |
bigint | 8个字节的带符号整数 | 1L | |
float | 4个字节的单精度浮点数 | 1.0 | |
double | 8个字节的双精度浮点数 | 1.0 | |
decimal | 任意精度的带符号小数 | 1.0 | |
string | 动态字符串 | “a”,‘b’ | |
varchar | 可设置长度的字符串 | “a”,‘b’ | |
char | 固定长度的字符串 | “a”,‘b’ | |
binary | 字节数组 | 无法表示 | |
timestamp | 时间戳,毫秒值精度 | ||
date | 日期 | ‘2021-09-18’ | |
interval | 时间频率间隔 | ||
复杂类型 | array | 有序的同类型的集合 | array(1,2) |
map | key-value,key必须为原始类型,value可以任意类型 | map('a','b',1,2) | |
struct | 字段集合,类型可以不同 | ||
union | 在有限取值范围内的一个值 |
1.2.2.2.创建表并指定字段之间的分隔符
语法:
create table if not exists '表名'(字段1 字段1类型 ,字段2 字段2类型,字段n 字段n类型,......) row format delimited fields terminated by '分隔符' stored as '文件存储格式' location '文件存储地址';
示例:
create table if not exists stu2(id int ,name string) row format delimited fields terminated by '\t' stored as textfile location '/user/stu2';
1.2.2.3.根据查询结果创建表
create table if not exists 新表 as select * from 旧表;
1.2.2.4.根据已经存在的表结构创建表
create table if not exists 新表 like 旧表;
1.2.2.5.查询表的类型
desc formatted 表名;
1.2.2.6.export导出与import导入表数据
示例:
create table techer2 like techer;
export table techer to '/export/techer';
import table techer2 from '/export/techer';
1.2.3.1.外部表说明
外部表因为是指定其他的hdfs路径的数据加载到表当中来,所以hive表会认为自己不完全独占这份数据,所以删除hive表的时候,数据仍然存放在hdfs当中,不会删掉,只会删除表的元数据
1.2.3.2.内部表和外部表的使用场景
示例:
每天将收集到的网站日志定期流入HDFS文本文件。在外部表(原始日志表)的基础上做大量的统计分析,用到的中间表、结果表使用内部表存储,数据通过SELECT+INSERT进入内部表。
1.2.3.3.操作案例
分别创建老师与学生表外部表,并向表中加载数据
创建老师表:
create external table techer (t_id string,t_name string) row format delimited fields terminated by '\t';
创建学生表:
create external table student (s_id string,s_name string,s_birth string , s_sex string ) row format delimited fields terminated by '\t';
从本地文件系统向表中加载数据
load data local inpath '/export/servers/hivedatas/student.csv' into table student;
加载数据并覆盖已有数据
load data local inpath '/export/servers/hivedatas/student.csv' overwrite into table student;
从hdfs文件系统向表中加载数据(需要提前将数据上传到hdfs文件系统,其实就是一个移动文件的操作)
cd /export/servers/hivedatas
hdfs dfs -mkdir -p /hivedatas
hdfs dfs -put techer.csv /hivedatas/
load data inpath '/hivedatas/techer.csv' into table techer;
如果删掉techer表,hdfs的数据仍然存在,并且重新创建表之后,表中就直接存在数据了,因为我们的techer表使用的是外部表,drop table之后,表当中的数据依然保留在hdfs上面了
在大数据中,最常用的一种思想就是分治,我们可以把大的文件切割划分成一个个的小的文件,这样每次操作一个小的文件就会很容易了,同样的道理,在hive当中也是支持这种思想的,就是我们可以把大的数据,按照每天,或者每小时进行切分成一个个的小的文件,这样去操作小的文件就会容易得多了
1.2.4.1.创建分区表语法
create table score(s_id string,c_id string, s_score int) partitioned by (month string) row format delimited fields terminated by '\t';
1.2.4.2.创建一个表带多个分区
create table score(s_id string,c_id string, s_score int) partitioned by (month string) row format delimited fields terminated by '\t';
1.2.4.3.加载数据到分区表中
load data local inpath '/export/servers/hivedatas/score.csv' into table score partition (month='201806');
1.2.4.4.加载数据到一个多分区的表中去
load data local inpath '/export/servers/hivedatas/score.csv' into table score2 partition(year='2018',month='06',day='01');
1.2.4.5.多分区联合查询使用union all来实现
select * from score where month = '201806' union all select * from score where month = '201807';
1.2.4.6.查看分区
show partitions 表名;
1.2.4.7.添加一个分区
alter table score add partition(month='201805');
1.2.4.8.同时添加多个分区
alter table score add partition(month='201804') partition(month = '201803');
注意:
添加分区之后就可以在hdfs文件系统当中看到表下面多了一个文件夹
1.2.4.9.删除分区
alter table score drop partition(month = '201806');
1.2.4.10.外部分区表综合练习
需求描述:
现在有一个文件score.csv文件,存放在集群的这个目录下/scoredatas/month=201806,这个文件每天都会生成,存放到对应的日期文件夹下面去,文件别人也需要公用,不能移动。需求,创建hive对应的表,并将数据加载到表中,进行数据统计分析,且删除表之后,数据不能删除
需求实现:
数据准备:
hdfs dfs -mkdir -p /scoredatas/month=201806
hdfs dfs -put score.csv /scoredatas/month=201806/
创建外部分区表,并指定文件数据存放目录
create external table score4(s_id string, c_id string,s_score int) partitioned by (month string) row format delimited fields terminated by '\t' location '/scoredatas';
进行表的修复,就是建立表与数据文件之间的一个关系映射
msck repair table score4;
修复成功之后即可看到数据已经全部加载到表当中去了
select * from score4;
第二种实现方式,上传数据之后手动添加分区即可
数据准备:
hdfs dfs -mkdir -p /scoredatas/month=201805
hdfs dfs -put score.csv /scoredatas/month=201805
修改表,进行手动添加方式
alter table score4 add partition(month='201805');
将数据按照指定字段划分到多个文件中
1.2.5.1.开启hive的桶表功能
set hive.enforce.bucketing=true;
1.2.5.2.设置reduce的个数
set mapreduce.job.reduces=3(个数根据实际情况调整);
1.2.5.3.创建桶表
create table course (c_id string,c_name string,t_id string) clustered by(c_id) into 3 buckets row format delimited fields terminated by '\t';
1.2.5.4.向分桶表加载数据
注意:
桶表的数据加载,只能通过insert overwrite。
hdfs dfs -put文件或者通过load data无法加载。
步骤:
1.创建普通表
2.普通表加载数据
3.通过insert overwrite 给桶表加载数据
示例:
1.创建普通表
create table course_common (c_id string,c_name string,t_id string) row format delimited fields terminated by '\t';
2.给普通表加载数据
load data local inpath '/export/servers/hivedatas/course.csv' into table course_common;
3.通过insert overwrite给桶表加载数据
insert overwrite table course select * from course_common cluster by(c_id);
1.2.6.1.表重命名
alter table old_table_name rename to new_table_name;
1.2.6.2.查看表结构
desc 表名;
1.2.6.3.添加列
alter table 表名 add columns (mycol string, mysco string);
1.2.6.4.更新列
alter table 表名 change column 旧列名 新列名 新列数据类型;
drop table 表名;
1.2.8.1.直接向分区表中插入数据
示例:
insert into table score3 partition(month ='201807') values ('001','002','100');
1.2.8.2.通过load方式加载数据
示例:
load data local inpath '/export/servers/hivedatas/score.csv' overwrite into table score partition(month='201806');
注意:
关键字overwrite 必须要有;
如果是Linux本地文件,需要加local关键字;
如果是HDFS文件,不需要加local关键字。
1.2.8.3.通过查询方式加载数据
insert overwrite table score4 partition(month = '201806') select s_id,c_id,s_score from score;
注: 关键字overwrite 必须要有
1.2.8.4.多插入模式
常用于实际生产环境当中,将一张表拆开成两部分或者多部分
示例:
给score表加载数据
load data local inpath '/export/servers/hivedatas/score.csv' overwrite into table score partition(month='201806');
创建第一部分表:
create table score_first( s_id string,c_id string) partitioned by (month string) row format delimited fields terminated by '\t' ;
创建第二部分表:
create table score_second(c_id string,s_score int) partitioned by (month string) row format delimited fields terminated by '\t';
分别给第一部分与第二部分表加载数据
from score insert overwrite table score_first partition(month='201806') select s_id,c_id insert overwrite table score_second partition(month = '201806') select c_id,s_score;
1.2.8.5.查询语句中创建表并加载数据(as select)
create table score5 as select * from score;
1.2.8.6.创建表时通过location指定加载数据路径
示例:
1) 创建表,并指定在hdfs上的位置
create external table score6 (s_id string,c_id string,s_score int) row format delimited fields terminated by '\t' location '/myscore6';
2)上传数据到hdfs上
hdfs dfs -mkdir -p /myscore6 hdfs dfs -put score.csv /myscore6;
3)查询数据
select * from score6;
1.2.9.1.inset导出
1.2.9.1.1.将查询的结果导出到本地
insert overwrite local directory '/export/servers/exporthive/a' select * from score;
1.2.9.1.2.将查询的结果格式化导出到本地
insert overwrite local directory '/export/servers/exporthive' row format delimited fields terminated by '\t' collection items terminated by '#' select * from student;
注意:
collection items terminated by '#' 对集合类型使用#来进行分割
1.2.9.1.3.将查询的结果导出到HDFS
insert overwrite directory '/export/servers/exporthive' row format delimited fields terminated by '\t' collection items terminated by '#' select * from score;
注意:
1.对于集合类型我们使用#来进行分割,因为这个表里面没有集合类型,所以加不加这个结果都一样
2.比起导出到本地,少了local命令
1.2.9.2.Hadoop命令导出到本地
在hive的shell窗口中输入:
dfs -get /export/servers/exporthive/000000_0 /export/servers/exporthive/local.txt;
1.2.9.3.hive shell命令导出
基本语法:(hive -f/-e 执行语句或者脚本 > file)
bin/hive -e "select * from myhive.score;" > /export/servers/exporthive/score.txt
1.2.9.4.export导出到HDFS
在hive的shell窗口输入:
export table score to '/export/exporthive/score';
1.2.9.5.sqoop导出
通过sqoop将hive表数据导出到DBMS数据库(如:mysql、postgresql)
具体语法请学习sqoop相关知识及命令
只能清空管理表,也就是内部表
truncate table 表名;
SELECT [ALL | DISTINCT] select_expr, select_expr, ...
FROM table_reference
[WHERE where_condition]
[GROUP BY col_list [HAVING condition]]
[CLUSTER BY col_list
| [DISTRIBUTE BY col_list] [SORT BY| ORDER BY col_list]
]
[LIMIT number]
注意:
1、order by 会对输入做全局排序,因此只有一个reducer时,会导致当输入规模较大时,需要较长的计算时间。
2、sort by不是全局排序是输入做全局排序,其在数据进入reducer前完成排序。因此,如果用sort by进行排序,并且设置mapred.reduce.tasks>1,则sort by只保证每个reducer的输出有序,不保证全局有序。
3、distribute by(字段)根据指定的字段将数据分到不同的reducer,且分发算法是hash散列。
4、Cluster by(字段) 除了具有Distribute by的功能外,还会对该字段进行排序
因此,如果分桶和sort字段是同一个时,此时,cluster by = distribute by + sort by
分桶表的作用:最大的作用是用来提高join操作的效率;
select * from score;
select s_id ,c_id from score;
1)重命名一个列。
2)便于计算。
3)紧跟列名,也可以在列名和别名之间加入关键字‘AS’
select s_id as myid ,c_id from score;
典型的查询会返回多行数据。LIMIT子句用于限制返回的行数。
select * from score limit 3;
1)使用WHERE 子句,将不满足条件的行过滤掉。
2)WHERE 子句紧随 FROM 子句。
3)案例实操
查询出分数大于60的数据
select * from score where s_score > 60;
1)使用LIKE运算选择类似的值
2)选择条件可以包含字符或数字:
% 代表零个或多个字符(任意个字符)。
_ 代表一个字符。
3)RLIKE子句是Hive中这个功能的一个扩展,其可以通过Java的正则表达式这个更强大的语言来指定匹配条件。
4)案例实操
(1)查找以8开头的所有成绩
select * from score where s_score like '8%';
(2)查找第二个数值为9的所有成绩数据
select * from score where s_score like '_9%';
(3)查找成绩中含9的所有成绩数据
select * from score where s_score rlike '[9]';
Hive支持通常的SQL JOIN语句,但是只支持等值连接,不支持非等值连接。
案例操作:
(1) 查询分数对应的姓名
SELECT s.s_id,s.s_score,stu.s_name,stu.s_birth FROM score s LEFT JOIN student stu ON s.s_id = stu.s_id;
1)好处
(1)使用别名可以简化查询。
(2)使用表名前缀可以提高执行效率。
2)案例实操
合并老师与课程表
select * from techer t join course c on t.t_id = c.t_id;
内连接:
只有进行连接的两个表中都存在与连接条件相匹配的数据才会被保留下来。(相当于交集)
select * from techer t inner join course c on t.t_id = c.t_id;
左外连接:
JOIN操作符左边表中符合WHERE子句的所有记录将会被返回。
案例:
查询老师对应的课程
select * from techer t left join course c on t.t_id = c.t_id;
右外连接:
JOIN操作符右边表中符合WHERE子句的所有记录将会被返回。
select * from techer t right join course c on t.t_id = c.t_id;
满外连接:
将会返回所有表中符合WHERE语句条件的所有记录。如果任一表的指定字段没有符合条件的值的话,那么就使用NULL值替代。
SELECT * FROM techer t FULL JOIN course c ON t.t_id = c.t_id ;
注意:连接 n个表,至少需要n-1个连接条件。例如:连接三个表,至少需要两个连接条件。
案例:
多表连接查询,查询老师对应的课程,以及对应的分数,对应的学生
select * from techer t left join course c on t.t_id = c.t_id left join score s on s.c_id = c.c_id left join student stu on s.s_id = stu.s_id;
大多数情况下,Hive会对每对JOIN连接对象启动一个MapReduce任务。本例中会首先启动一个MapReduce job对表techer和表course进行连接操作,然后会再启动一个MapReduce job将第一个MapReduce job的输出和表score;进行连接操作。
操作符 | 数据类型 | 描述 |
---|---|---|
A=B | 支持基本数据类型 | 如果A等于B则返回TRUE,反之返回FALSE |
A<=>B | 支持基本数据类型 | 如果A和B都为NULL,则返回TRUE,其他的和等号(=)操作符的结果一致,如果任一为NULL则结果为NULL |
A<>B,A!=B | 支持基本数据类型 | A或者B为NULL则返回NULL;如果A不等于B,则返回TRUE,反之返回FALSE |
A | 支持基本数据类型 | A或者B为NULL,则返回NULL;如果A小于B,则返回TRUE,反之返回FALSE |
A<=B | 支持基本数据类型 | A或者B为NULL,则返回NULL;如果A小于等于B,则返回TRUE,反之返回FALSE |
A>B | 支持基本数据类型 | A或者B为NULL,则返回NULL;如果A大于B,则返回TRUE,反之返回FALSE |
A>=B | 支持基本数据类型 | A或者B为NULL,则返回NULL;如果A大于等于B,则返回TRUE,反之返回FALSE |
A [not] between B and C | 支持基本数据类型 | 如果A,B或者C任一为NULL,则结果为NULL。如果A的值大于等于B而且小于或等于C,则结果为TRUE,反之为FALSE。如果使用NOT关键字则可达到相反的效果。 |
A is null | 支持所有数据类型 | 如果A等于NULL,则返回TRUE,反之返回FALSE |
A is not null | 支持所有数据类型 | 如果A不等于NULL,则返回TRUE,反之返回FALSE |
in(数值1,数值2) | 支持所有数据类型 | 使用 IN运算显示列表中的值 |
A [not] like B | 支持String类型 | B是一个SQL下的简单正则表达式,如果A与其匹配的话,则返回TRUE;反之返回FALSE。B的表达式说明如下:‘x%’表示A必须以字母‘x’开头,‘%x’表示A必须以字母’x’结尾,而‘%x%’表示A包含有字母’x’,可以位于开头,结尾或者字符串中间。如果使用NOT关键字则可达到相反的效果。 |
A rlike B,A regexp B | 支持String类型 | B是一个正则表达式,如果A与其匹配,则返回TRUE;反之返回FALSE。匹配使用的是JDK中的正则表达式接口实现的,因为正则也依据其中的规则。例如,正则表达式必须和整个字符串A相匹配,而不是只需与其字符串匹配。 |
GROUP BY语句通常会和聚合函数一起使用,按照一个或者多个列队结果进行分组,然后对每个组执行聚合操作。
案例实操:
(1)计算每个学生的平均分数
select s_id ,avg(s_score) from score group by s_id;
(2)计算每个学生最高成绩
select s_id ,max(s_score) from score group by s_id;
注意:
注意group by的字段,必须是select后面的字段,select后面的字段不能比group by的字段多
group by语法中出现在select 后面的字段两个要求
1 字段是分组字段
2 必须使用聚合函数应用
1)having与where不同点
(1)where针对表中的列发挥作用,查询数据;having针对查询结果中的列发挥作用,筛选数据。
(2)where后面不能写分组函数,而having后面可以使用分组函数。
(3)having只用于group by分组统计语句。
2)案例实操:
求每个学生的平均分数
select s_id ,avg(s_score) from score group by s_id;
求每个学生平均分数大于85的人
select s_id ,avg(s_score) avgscore from score group by s_id having avgscore > 85;
Order By:全局排序,一个reduce
1)使用 ORDER BY 子句排序
ASC(ascend): 升序(默认)
DESC(descend): 降序
2)ORDER BY 子句在SELECT语句的结尾。
3)案例实操
(1)查询学生的成绩,并按照分数降序排列
SELECT * FROM student s LEFT JOIN score sco ON s.s_id = sco.s_id ORDER BY sco.s_score DESC;
(2)查询学生的成绩,并按照分数升序排列
SELECT * FROM student s LEFT JOIN score sco ON s.s_id = sco.s_id ORDER BY sco.s_score asc;
按照分数的平均值排序
select s_id ,avg(s_score) avg from score group by s_id order by avg;
按照学生id和成绩进行排序
select s_id ,avg(s_score) avg from score group by s_id order by s_id,avg;
Sort By:每个MapReduce内部进行排序,对全局结果集来说不是排序。
1)设置reduce个数
set mapreduce.job.reduces=3;
2)查看设置reduce个数
set mapreduce.job.reduces;
3)查询成绩按照成绩降序排列
select * from score sort by s_score;
1) 将查询结果导入到文件中(按照成绩降序排列)
insert overwrite local directory '/export/servers/hivedatas/sort' select * from score sort by s_score;
Distribute By:类似MR中partition,进行分区,结合sort by使用。
注意,Hive要求DISTRIBUTE BY语句要写在SORT BY语句之前。
对于distribute by进行测试,一定要分配多reduce进行处理,否则无法看到distribute by的效果。
案例实操:
(1) 先按照学生id进行分区,再按照学生成绩进行排序。
设置reduce的个数,将我们对应的s_id划分到对应的reduce当中去
set mapreduce.job.reduces=7;
通过distribute by 进行数据的分区
insert overwrite local directory '/export/servers/hivedatas/sort' select * from score distribute by s_id sort by s_score;
当distribute by和sort by字段相同时,可以使用cluster by方式。
cluster by除了具有distribute by的功能外还兼具sort by的功能。但是排序只能是倒序排序,不能指定排序规则为ASC或者DESC。
1) 以下两种写法等价
select * from score cluster by s_id;
select * from score distribute by s_id sort by s_id;
求数量
求最大值
求最小值
求和
求平均值