优化阅读格式

This commit is contained in:
heibaiying
2019-07-31 17:18:07 +08:00
parent ceb868fe13
commit ca7c99802b
91 changed files with 4059 additions and 4058 deletions

View File

@ -33,7 +33,7 @@
为了演示查询操作,这里需要预先创建三张表,并加载测试数据。
> 数据文件emp.txtdept.txt可以从本仓库的[resources](https://github.com/heibaiying/BigData-Notes/tree/master/resources)目录下载。
> 数据文件 emp.txtdept.txt 可以从本仓库的[resources](https://github.com/heibaiying/BigData-Notes/tree/master/resources) 目录下载。
### 1.1 员工表
@ -110,7 +110,7 @@ SELECT * FROM emp;
### 2.2 WHERE
```sql
-- 查询10号部门中员工编号大于 7782 的员工信息
-- 查询 10 号部门中员工编号大于 7782 的员工信息
SELECT * FROM emp WHERE empno > 7782 AND deptno = 10;
```
@ -118,7 +118,7 @@ SELECT * FROM emp WHERE empno > 7782 AND deptno = 10;
### 2.3 DISTINCT
Hive支持使用DISTINCT关键字去重。
Hive 支持使用 DISTINCT 关键字去重。
```sql
-- 查询所有工作类型
@ -129,7 +129,7 @@ SELECT DISTINCT job FROM emp;
### 2.4 分区查询
分区查询(Partition Based Queries),可以指定某个分区或者分区范围。
分区查询 (Partition Based Queries),可以指定某个分区或者分区范围。
```sql
-- 查询分区表中部门编号在[20,40]之间的员工
@ -142,7 +142,7 @@ WHERE emp_ptn.deptno >= 20 AND emp_ptn.deptno <= 40;
### 2.5 LIMIT
```sql
-- 查询薪资最高的5名员工
-- 查询薪资最高的 5 名员工
SELECT * FROM emp ORDER BY sal DESC LIMIT 5;
```
@ -150,7 +150,7 @@ SELECT * FROM emp ORDER BY sal DESC LIMIT 5;
### 2.6 GROUP BY
Hive支持使用GROUP BY进行分组聚合操作。
Hive 支持使用 GROUP BY 进行分组聚合操作。
```sql
set hive.map.aggr=true;
@ -159,20 +159,20 @@ set hive.map.aggr=true;
SELECT deptno,SUM(sal) FROM emp GROUP BY deptno;
```
`hive.map.aggr`控制程序如何进行聚合。默认值为false。如果设置为trueHive会在map阶段就执行一次聚合。这可以提高聚合效率但需要消耗更多内存。
`hive.map.aggr` 控制程序如何进行聚合。默认值为 false。如果设置为 trueHive 会在 map 阶段就执行一次聚合。这可以提高聚合效率,但需要消耗更多内存。
### 2.7 ORDER AND SORT
可以使用ORDER BY或者Sort BY对查询结果进行排序排序字段可以是整型也可以是字符串如果是整型则按照大小排序如果是字符串则按照字典序排序。ORDER BY 和 SORT BY 的区别如下:
可以使用 ORDER BY 或者 Sort BY 对查询结果进行排序排序字段可以是整型也可以是字符串如果是整型则按照大小排序如果是字符串则按照字典序排序。ORDER BY 和 SORT BY 的区别如下:
+ 使用ORDER BY时会有一个Reducer对全部查询结果进行排序可以保证数据的全局有序性
+ 使用SORT BY时只会在每个Reducer中进行排序这可以保证每个Reducer的输出数据是有序的但不能保证全局有序。
+ 使用 ORDER BY 时会有一个 Reducer 对全部查询结果进行排序,可以保证数据的全局有序性;
+ 使用 SORT BY 时只会在每个 Reducer 中进行排序,这可以保证每个 Reducer 的输出数据是有序的,但不能保证全局有序。
由于ORDER BY的时间可能很长如果你设置了严格模式(hive.mapred.mode = strict),则其后面必须再跟一个`limit`子句。
由于 ORDER BY 的时间可能很长,如果你设置了严格模式 (hive.mapred.mode = strict),则其后面必须再跟一个 `limit` 子句。
> hive.mapred.mode默认值是nonstrict ,也就是非严格模式。
> hive.mapred.mode 默认值是 nonstrict ,也就是非严格模式。
```sql
-- 查询员工工资,结果按照部门升序,按照工资降序排列
@ -183,10 +183,10 @@ SELECT empno, deptno, sal FROM emp ORDER BY deptno ASC, sal DESC;
### 2.8 HAVING
可以使用HAVING对分组数据进行过滤。
可以使用 HAVING 对分组数据进行过滤。
```sql
-- 查询工资总和大于9000的所有部门
-- 查询工资总和大于 9000 的所有部门
SELECT deptno,SUM(sal) FROM emp GROUP BY deptno HAVING SUM(sal)>9000;
```
@ -194,11 +194,11 @@ 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字句。
默认情况下MapReduce 程序会对 Map 输出结果的 Key 值进行散列,并均匀分发到所有 Reducer 上。如果想要把具有相同 Key 值的数据分发到同一个 Reducer 进行处理,这就需要使用 DISTRIBUTE BY 字句。
需要注意的是DISTRIBUTE BY虽然能保证具有相同Key值的数据分发到同一个Reducer但是不能保证数据在Reducer上是有序的。情况如下
需要注意的是DISTRIBUTE BY 虽然能保证具有相同 Key 值的数据分发到同一个 Reducer但是不能保证数据在 Reducer 上是有序的。情况如下:
把以下5个数据发送到两个Reducer上进行处理
把以下 5 个数据发送到两个 Reducer 上进行处理:
```properties
k1
@ -208,7 +208,7 @@ k3
k1
```
Reducer1得到如下乱序数据
Reducer1 得到如下乱序数据:
```properties
k1
@ -217,17 +217,17 @@ k1
```
Reducer2得到数据如下
Reducer2 得到数据如下:
```properties
k4
k3
```
如果想让Reducer上的数据时有序的可以结合`SORT BY`使用(示例如下)或者使用下面我们将要介绍的CLUSTER BY。
如果想让 Reducer 上的数据时有序的,可以结合 `SORT BY` 使用 (示例如下),或者使用下面我们将要介绍的 CLUSTER BY。
```sql
-- 将数据按照部门分发到对应的Reducer上处理
-- 将数据按照部门分发到对应的 Reducer 上处理
SELECT empno, deptno, sal FROM emp DISTRIBUTE BY deptno SORT BY deptno ASC;
```
@ -235,7 +235,7 @@ 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`可以保证数据在全局是有序的。
如果 `SORT BY``DISTRIBUTE BY` 指定的是相同字段,且 SORT BY 排序规则是 ASC此时可以使用 `CLUSTER BY` 进行替换,同时 `CLUSTER BY` 可以保证数据在全局是有序的。
```sql
SELECT empno, deptno, sal FROM emp CLUSTER BY deptno ;
@ -245,9 +245,9 @@ SELECT empno, deptno, sal FROM emp CLUSTER BY deptno ;
## 三、多表联结查询
Hive支持内连接外连接左外连接右外连接笛卡尔连接这和传统数据库中的概念是一致的可以参见下图。
Hive 支持内连接,外连接,左外连接,右外连接,笛卡尔连接,这和传统数据库中的概念是一致的,可以参见下图。
需要特别强调JOIN语句的关联条件必须用ON指定不能用WHERE指定否则就会先做笛卡尔积再过滤这会导致你得不到预期的结果(下面的演示会有说明)。
需要特别强调JOIN 语句的关联条件必须用 ON 指定,不能用 WHERE 指定,否则就会先做笛卡尔积,再过滤,这会导致你得不到预期的结果 (下面的演示会有说明)。
<div align="center"> <img width="600px" src="https://github.com/heibaiying/BigData-Notes/blob/master/pictures/sql-join.jpg"/> </div>
@ -256,7 +256,7 @@ Hive支持内连接外连接左外连接右外连接笛卡尔连接
### 3.1 INNER JOIN
```sql
-- 查询员工编号为7369的员工的详细信息
-- 查询员工编号为 7369 的员工的详细信息
SELECT e.*,d.* FROM
emp e JOIN dept d
ON e.deptno = d.deptno
@ -268,7 +268,7 @@ SELECT a.val, b.val, c.val FROM a JOIN b ON (a.key = b.key1) JOIN c ON (c.key =
### 3.2 LEFT OUTER JOIN
LEFT OUTER JOIN 和 LEFT JOIN是等价的。
LEFT OUTER JOIN 和 LEFT JOIN 是等价的。
```sql
-- 左连接
@ -286,7 +286,7 @@ FROM emp e RIGHT OUTER JOIN dept d
ON e.deptno = d.deptno;
```
执行右连接后由于40号部门下没有任何员工所以此时员工信息为NULL。这个查询可以很好的复述上面提到的——JOIN语句的关联条件必须用ON指定不能用WHERE指定。你可以把ON改成WHERE你会发现无论如何都查不出40号部门这条数据因为笛卡尔运算不会有(NULL, 40)这种情况。
执行右连接后,由于 40 号部门下没有任何员工,所以此时员工信息为 NULL。这个查询可以很好的复述上面提到的——JOIN 语句的关联条件必须用 ON 指定,不能用 WHERE 指定。你可以把 ON 改成 WHERE你会发现无论如何都查不出 40 号部门这条数据,因为笛卡尔运算不会有 (NULL, 40) 这种情况。
<div align="center"> <img width="700px" src="https://github.com/heibaiying/BigData-Notes/blob/master/pictures/hive-right-join.png"/> </div>
@ -303,7 +303,7 @@ ON e.deptno = d.deptno;
LEFT SEMI JOIN (左半连接)是 IN/EXISTS 子查询的一种更高效的实现。
+ JOIN 子句中右边的表只能在 ON 子句中设置过滤条件;
+ 查询结果只包含左边表的数据所以只能SELECT左表中的列。
+ 查询结果只包含左边表的数据,所以只能 SELECT 左表中的列。
```sql
-- 查询在纽约办公的所有员工信息
@ -318,7 +318,7 @@ WHERE emp.deptno IN (SELECT deptno FROM dept WHERE loc="NEW YORK");
### 3.6 JOIN
笛卡尔积连接,这个连接日常的开发中可能很少遇到,且性能消耗比较大,基于这个原因,如果在严格模式下(hive.mapred.mode = strict)Hive会阻止用户执行此操作。
笛卡尔积连接,这个连接日常的开发中可能很少遇到,且性能消耗比较大,基于这个原因,如果在严格模式下 (hive.mapred.mode = strict)Hive 会阻止用户执行此操作。
```sql
SELECT * FROM emp JOIN dept;
@ -330,13 +330,13 @@ SELECT * FROM emp JOIN dept;
### 4.1 STREAMTABLE
在多表进行联结的时候如果每个ON字句都使用到共同的列如下面的`b.key`此时Hive会进行优化将多表JOIN在同一个map / reduce作业上进行。同时假定查询的最后一个表如下面的 c 表是最大的一个表在对每行记录进行JOIN操作时它将尝试将其他的表缓存起来然后扫描最后那个表进行计算。因此用户需要保证查询的表的大小从左到右是依次增加的。
在多表进行联结的时候,如果每个 ON 字句都使用到共同的列(如下面的 `b.key`),此时 Hive 会进行优化,将多表 JOIN 在同一个 map / reduce 作业上进行。同时假定查询的最后一个表(如下面的 c 表)是最大的一个表,在对每行记录进行 JOIN 操作时,它将尝试将其他的表缓存起来,然后扫描最后那个表进行计算。因此用户需要保证查询的表的大小从左到右是依次增加的。
```sql
`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() */`标志,用于标识最大的表,示例如下:
然后用户并非需要总是把最大的表放在查询语句的最后面Hive 提供了 `/*+ STREAMTABLE() */` 标志,用于标识最大的表,示例如下:
```sql
SELECT /*+ STREAMTABLE(d) */ e.*,d.*
@ -349,7 +349,7 @@ WHERE job='CLERK';
### 4.2 MAPJOIN
如果所有表中只有一张表是小表那么Hive把这张小表加载到内存中。这时候程序会在map阶段直接拿另外一个表的数据和内存中表数据做匹配由于在map就进行了JOIN操作从而可以省略reduce过程这样效率可以提升很多。Hive中提供了`/*+ MAPJOIN() */`来标记小表,示例如下:
如果所有表中只有一张表是小表,那么 Hive 把这张小表加载到内存中。这时候程序会在 map 阶段直接拿另外一个表的数据和内存中表数据做匹配,由于在 map 就进行了 JOIN 操作,从而可以省略 reduce 过程这样效率可以提升很多。Hive 中提供了 `/*+ MAPJOIN() */` 来标记小表,示例如下:
```sql
SELECT /*+ MAPJOIN(d) */ e.*,d.*
@ -372,20 +372,20 @@ SELECT current_database()
## 六、本地模式
在上面演示的语句中大多数都会触发MapReduce, 少部分不会触发,比如`select * from emp limit 5`就不会触发MR此时Hive只是简单的读取数据文件中的内容然后格式化后进行输出。在需要执行MapReduce的查询中你会发现执行时间可能会很长这时候你可以选择开启本地模式。
在上面演示的语句中,大多数都会触发 MapReduce, 少部分不会触发,比如 `select * from emp limit 5` 就不会触发 MR此时 Hive 只是简单的读取数据文件中的内容,然后格式化后进行输出。在需要执行 MapReduce 的查询中,你会发现执行时间可能会很长,这时候你可以选择开启本地模式。
```sql
--本地模式默认关闭,需要手动开启此功能
SET hive.exec.mode.local.auto=true;
```
启用后Hive将分析查询中每个map-reduce作业的大小如果满足以下条件则可以在本地运行它
启用后Hive 将分析查询中每个 map-reduce 作业的大小,如果满足以下条件,则可以在本地运行它:
- 作业的总输入大小低于hive.exec.mode.local.auto.inputbytes.max默认为128MB
- map-tasks的总数小于hive.exec.mode.local.auto.tasks.max默认为4
- 所需的reduce任务总数为1或0。
- 作业的总输入大小低于hive.exec.mode.local.auto.inputbytes.max默认为 128MB
- map-tasks 的总数小于hive.exec.mode.local.auto.tasks.max默认为 4
- 所需的 reduce 任务总数为 1 或 0。
因为我们测试的数据集很小所以你再次去执行上面涉及MR操作的查询你会发现速度会有显著的提升。
因为我们测试的数据集很小,所以你再次去执行上面涉及 MR 操作的查询,你会发现速度会有显著的提升。