Hive 学习之路(八)—— Hive 数据查询详解
一、数据准备
为了演示查询操作,这里需要预先创建三张表,并加载测试数据。
数据文件emp.txt和dept.txt可以从本仓库的resources目录下载。
1.1 员工表
-- 建表语句
CREATE TABLE emp(
empno INT, -- 员工表编号
ename STRING, -- 员工姓名
job STRING, -- 职位类型
mgr INT,
hiredate TIMESTAMP, --雇佣日期
sal DECIMAL(7,2), --工资
comm DECIMAL(7,2),
deptno INT) --部门编号
ROW FORMAT DELIMITED FIELDS TERMINATED BY "\t";
--加载数据
LOAD DATA LOCAL INPATH "/usr/file/emp.txt" OVERWRITE INTO TABLE emp;
1.2 部门表
-- 建表语句
CREATE TABLE dept(
deptno INT, --部门编号
dname STRING, --部门名称
loc STRING --部门所在的城市
)
ROW FORMAT DELIMITED FIELDS TERMINATED BY "\t";
--加载数据
LOAD DATA LOCAL INPATH "/usr/file/dept.txt" OVERWRITE INTO TABLE dept;
1.3 分区表
这里需要额外创建一张分区表,主要是为了演示分区查询:
CREATE EXTERNAL TABLE emp_ptn(
empno INT,
ename STRING,
job STRING,
mgr INT,
hiredate TIMESTAMP,
sal DECIMAL(7,2),
comm DECIMAL(7,2)
)
PARTITIONED BY (deptno INT) -- 按照部门编号进行分区
ROW FORMAT DELIMITED FIELDS TERMINATED BY "\t";
--加载数据
LOAD DATA LOCAL INPATH "/usr/file/emp.txt" OVERWRITE INTO TABLE emp_ptn PARTITION (deptno=20)
LOAD DATA LOCAL INPATH "/usr/file/emp.txt" OVERWRITE INTO TABLE emp_ptn PARTITION (deptno=30)
LOAD DATA LOCAL INPATH "/usr/file/emp.txt" OVERWRITE INTO TABLE emp_ptn PARTITION (deptno=40)
LOAD DATA LOCAL INPATH "/usr/file/emp.txt" OVERWRITE INTO TABLE emp_ptn PARTITION (deptno=50)
二、单表查询
2.1 SELECT
-- 查询表中全部数据
SELECT * FROM emp;
2.2 WHERE
-- 查询10号部门中员工编号大于 7782 的员工信息
SELECT * FROM emp WHERE empno > 7782 AND deptno = 10;
2.3 DISTINCT
Hive支持使用DISTINCT关键字去重。
-- 查询所有工作类型
SELECT DISTINCT job FROM emp;
2.4 分区查询
分区查询(Partition Based Queries),可以指定某个分区或者分区范围。
-- 查询分区表中部门编号在[20,40]之间的员工
SELECT emp_ptn.* FROM emp_ptn
WHERE emp_ptn.deptno >= 20 AND emp_ptn.deptno <= 40;
2.5 LIMIT
-- 查询薪资最高的5名员工
SELECT * FROM emp ORDER BY sal DESC LIMIT 5;
2.6 GROUP BY
Hive支持使用GROUP BY进行分组聚合操作。
set hive.map.aggr=true;
-- 查询各个部门薪酬综合
SELECT deptno,SUM(sal) FROM emp GROUP BY deptno;
hive.map.aggr控制程序如何进行聚合。默认值为false。如果设置为true,Hive会在map阶段就执行一次聚合。这可以提高聚合效率,但需要消耗更多内存。
2.7 ORDER AND SORT
可以使用ORDER BY或者Sort BY对查询结果进行排序,排序字段可以是整型也可以是字符串:如果是整型,则按照大小排序;如果是字符串,则按照字典序排序。ORDER BY 和 SORT BY 的区别如下:
- 使用ORDER BY时会有一个Reducer对全部查询结果进行排序,可以保证数据的全局有序性;
- 使用SORT BY时只会在每个Reducer中进行排序,这可以保证每个Reducer的输出数据是有序的,但不能保证全局有序。
由于ORDER BY的时间可能很长,如果你设置了严格模式(hive.mapred.mode = strict),则其后面必须再跟一个limit子句。
注 :hive.mapred.mode默认值是nonstrict ,也就是非严格模式。
-- 查询员工工资,结果按照部门升序,按照工资降序排列
SELECT empno, deptno, sal FROM emp ORDER BY deptno ASC, sal DESC;
2.8 HAVING
可以使用HAVING对分组数据进行过滤。
-- 查询工资总和大于9000的所有部门
SELECT deptno,SUM(sal) FROM emp GROUP BY deptno HAVING SUM(sal)>9000;
2.9 DISTRIBUTE BY
默认情况下,MapReduce程序会对Map输出结果的Key值进行散列,并均匀分发到所有Reducer上。如果想要把具有相同Key值的数据分发到同一个Reducer进行处理,这就需要使用DISTRIBUTE BY字句。
需要注意的是,DISTRIBUTE BY虽然能保证具有相同Key值的数据分发到同一个Reducer,但是不能保证数据在Reducer上是有序的。情况如下:
把以下5个数据发送到两个Reducer上进行处理:
k1
k2
k4
k3
k1
Reducer1得到如下乱序数据:
k1
k2
k1
Reducer2得到数据如下:
k4
k3
如果想让Reducer上的数据时有序的,可以结合SORT BY使用(示例如下),或者使用下面我们将要介绍的CLUSTER BY。
-- 将数据按照部门分发到对应的Reducer上处理
SELECT empno, deptno, sal FROM emp DISTRIBUTE BY deptno SORT BY deptno ASC;
2.10 CLUSTER BY
如果SORT BY和DISTRIBUTE BY指定的是相同字段,且SORT BY排序规则是ASC,此时可以使用CLUSTER BY进行替换,同时CLUSTER BY可以保证数据在全局是有序的。
SELECT empno, deptno, sal FROM emp CLUSTER BY deptno ;
三、多表联结查询
Hive支持内连接,外连接,左外连接,右外连接,笛卡尔连接,这和传统数据库中的概念是一致的,可以参见下图。
需要特别强调:JOIN语句的关联条件必须用ON指定,不能用WHERE指定,否则就会先做笛卡尔积,再过滤,这会导致你得不到预期的结果(下面的演示会有说明)。

3.1 INNER JOIN
-- 查询员工编号为7369的员工的详细信息
SELECT e.*,d.* FROM
emp e JOIN dept d
ON e.deptno = d.deptno
WHERE empno=7369;
--如果是三表或者更多表连接,语法如下
SELECT a.val, b.val, c.val FROM a JOIN b ON (a.key = b.key1) JOIN c ON (c.key = b.key1)
3.2 LEFT OUTER JOIN
LEFT OUTER JOIN 和 LEFT JOIN是等价的。
-- 左连接
SELECT e.*,d.*
FROM emp e LEFT OUTER JOIN dept d
ON e.deptno = d.deptno;
3.3 RIGHT OUTER JOIN
--右连接
SELECT e.*,d.*
FROM emp e RIGHT OUTER JOIN dept d
ON e.deptno = d.deptno;
执行右连接后,由于40号部门下没有任何员工,所以此时员工信息为NULL。这个查询可以很好的复述上面提到的——JOIN语句的关联条件必须用ON指定,不能用WHERE指定。你可以把ON改成WHERE,你会发现无论如何都查不出40号部门这条数据,因为笛卡尔运算不会有(NULL, 40)这种情况。

3.4 FULL OUTER JOIN
SELECT e.*,d.*
FROM emp e FULL OUTER JOIN dept d
ON e.deptno = d.deptno;
3.5 LEFT SEMI JOIN
LEFT SEMI JOIN (左半连接)是 IN/EXISTS 子查询的一种更高效的实现。
- JOIN 子句中右边的表只能在 ON 子句中设置过滤条件;
- 查询结果只包含左边表的数据,所以只能SELECT左表中的列。
-- 查询在纽约办公的所有员工信息
SELECT emp.*
FROM emp LEFT SEMI JOIN dept
ON emp.deptno = dept.deptno AND dept.loc="NEW YORK";
--上面的语句就等价于
SELECT emp.* FROM emp
WHERE emp.deptno IN (SELECT deptno FROM dept WHERE loc="NEW YORK");
3.6 JOIN
笛卡尔积连接,这个连接日常的开发中可能很少遇到,且性能消耗比较大,基于这个原因,如果在严格模式下(hive.mapred.mode = strict),Hive会阻止用户执行此操作。
SELECT * FROM emp JOIN dept;
四、JOIN优化
4.1 STREAMTABLE
在多表进行联结的时候,如果每个ON字句都使用到共同的列(如下面的b.key),此时Hive会进行优化,将多表JOIN在同一个map / reduce作业上进行。同时假定查询的最后一个表(如下面的 c 表)是最大的一个表,在对每行记录进行JOIN操作时,它将尝试将其他的表缓存起来,然后扫描最后那个表进行计算。因此用户需要保证查询的表的大小从左到右是依次增加的。
`SELECT a.val, b.val, c.val FROM a JOIN b ON (a.key = b.key) JOIN c ON (c.key = b.key)`
然后,用户并非需要总是把最大的表放在查询语句的最后面,Hive提供了/*+ STREAMTABLE() */标志,用于标识最大的表,示例如下:
SELECT /*+ STREAMTABLE(d) */ e.*,d.*
FROM emp e JOIN dept d
ON e.deptno = d.deptno
WHERE job='CLERK';
4.2 MAPJOIN
如果所有表中只有一张表是小表,那么Hive把这张小表加载到内存中。这时候程序会在map阶段直接拿另外一个表的数据和内存中表数据做匹配,由于在map就进行了JOIN操作,从而可以省略reduce过程,这样效率可以提升很多。Hive中提供了/*+ MAPJOIN() */来标记小表,示例如下:
SELECT /*+ MAPJOIN(d) */ e.*,d.*
FROM emp e JOIN dept d
ON e.deptno = d.deptno
WHERE job='CLERK';
五、SELECT的其他用途
查看当前数据库:
SELECT current_database()
六、本地模式
在上面演示的语句中,大多数都会触发MapReduce, 少部分不会触发,比如select * from emp limit 5就不会触发MR,此时Hive只是简单的读取数据文件中的内容,然后格式化后进行输出。在需要执行MapReduce的查询中,你会发现执行时间可能会很长,这时候你可以选择开启本地模式。
--本地模式默认关闭,需要手动开启此功能
SET hive.exec.mode.local.auto=true;
启用后,Hive将分析查询中每个map-reduce作业的大小,如果满足以下条件,则可以在本地运行它:
- 作业的总输入大小低于:hive.exec.mode.local.auto.inputbytes.max(默认为128MB);
- map-tasks的总数小于:hive.exec.mode.local.auto.tasks.max(默认为4);
- 所需的reduce任务总数为1或0。
因为我们测试的数据集很小,所以你再次去执行上面涉及MR操作的查询,你会发现速度会有显著的提升。
参考资料
更多大数据系列文章可以参见个人 GitHub 开源项目: 程序员大数据入门指南
Hive 学习之路(八)—— Hive 数据查询详解的更多相关文章
- Hive 系列(八)—— Hive 数据查询详解
一.数据准备 为了演示查询操作,这里需要预先创建三张表,并加载测试数据. 数据文件 emp.txt 和 dept.txt 可以从本仓库的resources 目录下载. 1.1 员工表 -- 建表语句 ...
- 入门大数据---Hive数据查询详解
一.数据准备 为了演示查询操作,这里需要预先创建三张表,并加载测试数据. 数据文件 emp.txt 和 dept.txt 可以从本仓库的resources 目录下载. 1.1 员工表 -- 建表语句 ...
- Hibernate学习第4天--HQL——QBC查询详解,抓取策略优化。
上次课回顾: l Hibernate的一对多 n 表与表之间关系 u 一对多关系 u 多对多关系 u 一对一关系 n Hibernate的一对多配置 u 搭建Hibernate基本环境 ...
- MongoDB数据查询详解
查询全部 db.infos.find(); db.infos.find({"url":"www.baidu.com"}); id不要显示出来 db.info ...
- Hadoop学习之路(8)Yarn资源调度系统详解
文章目录 1.Yarn介绍 2.Yarn架构 2.1 .ResourceManager 2.2 .ApplicationMaster 2.3 .NodeManager 2.4 .Container 2 ...
- ElasticSearch7.3学习(二十)----采用restful风格查询详解
1.Query DSL入门 1.1 DSL DSL:Domain Specified Language,特定领域的语言.es特有的搜索语言,可在请求体中携带搜索条件,功能强大. 查询全部 GET /b ...
- django orm 数据查询详解
一 在django里面创建模型 from django.db import models class Blog(models.Model): name = models.CharField(max_l ...
- 性能测试学习之路 (二)jmeter详解(jmeter执行顺序 && 作用域 && 断言 && 事务 &&集合点 )
1 Jmeter 工作区介绍 jmeter工作区分为3个部分:目录树.测试计划编辑区域.菜单栏. 2 Jmeter 执行顺序规则 Jmeter执行顺序规则如下: 配置元件 前置处理器 定时器 采样器s ...
- Webwork 学习之路【04】Configuration 详解
Webwork做为经典的Web MVC 框架,个人觉得源码中配置文件这部分代码的实现十分考究. 支持自定义自己的配置文件.自定义配置文件读取类.自定义国际化支持. 可以作为参考,单独引入到其他项目中, ...
随机推荐
- python 左旋转字符串
比较简单的一道题 汇编语言中有一种移位指令叫做循环左移(ROL),现在有个简单的任务,就是用字符串模拟这个指令的运算结果.对于一个给定的字符序列S,请你把其循环左移K位后的序列输出.例如,字符序列S= ...
- windown下linux子系统的安装和卸载
原文:windown下linux子系统的安装和卸载 安装 第一步 打开开发人员模式 第二步 勾选适用linux的window子系统 第三步 打开powershell 第四步 在PowerShe ...
- 图像处理结果的度量 —— SNR、PSNR、SSIM
衡量两幅图像的相似度: SNR/PSNR SSIM 1. SNR vs PSNR about SNR 和 PSNR MSE:mean squared error ∑x=1Nx∑y=1Ny(f(x,y) ...
- 学习vi和vim编辑(4):高速移动定位
平时.第一步是编辑文本需要做将光标移动到需要编辑.因此,根据需要,将光标移动到目标数字键来编辑文本的速度在一定程度上. 一篇文章.主要介绍怎样高速移动光标. 依据屏幕来移动: 在一个有几千行文本的文件 ...
- 倒计时的CountDownTimer
直接看这里吧,我仅仅是搬运工. 定时运行在一段时候后停止的倒计时,在倒计时运行过程中会在固定间隔时间得到通知(译者:触发onTick方法),以下的样例显示在一个文本框中显示一个30s倒计时: , 1 ...
- OpenGL(二十三) 各向异性纹理过滤
如果使用一般的纹理过滤,当观察方向跟模型表面不是相互垂直的的情况下,会出现纹理信息的丢失,表现为图像看上去比较模糊,如下图所示,远处场景的细节信息很差: 针对这种情况,可以采用同向异性过滤的方式处理纹 ...
- matlab 类型转换(类型判断)
char:Convert to character array,转换为字符数组:matlab 下没有 str 字符串类型转换: char(0-255) ⇒ ASCII 码的转换: im2double( ...
- Windows 编译libcurl(openssl+zlib)(使用VC编译)
libcurl主要功能就是用不同的协议连接和沟通不同的服务器,如果使用HTTPS,需要OpenSSL libcurl https://curl.haxx.se/download.html 下载Sour ...
- ios-利用键盘通知处理键盘出现时遮挡控件问题
-(void)viewDidLoad { NSNotificationCenter *center = [NSNotificationCenter defaultCenter]; //注册键盘显示通知 ...
- ios7 获取UITablleViewCell
iOS7之前UITablleViewCell中得contentView得superView就是UITableViewCell.但是在iOS7得时候,contentView得superView确实UIT ...