From 2c37679b55910b378e2977f5f15e3bb102c94a11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=BD=97=E7=A5=A5?= <1366971433@qq.com> Date: Mon, 29 Apr 2019 17:17:32 +0800 Subject: [PATCH] =?UTF-8?q?Hive=E6=95=B0=E6=8D=AE=E6=9F=A5=E8=AF=A2?= =?UTF-8?q?=E8=AF=A6=E8=A7=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 13 +- notes/Hive常用DML操作.md | 29 ++- notes/Hive数据查询详解.md | 407 ++++++++++++++++++++++++++++++++ pictures/hive-order-by.png | Bin 0 -> 7336 bytes pictures/hive-right-join.png | Bin 0 -> 39956 bytes pictures/sql-join.jpg | Bin 0 -> 50515 bytes resources/dept.txt | 4 + 7 files changed, 438 insertions(+), 15 deletions(-) create mode 100644 notes/Hive数据查询详解.md create mode 100644 pictures/hive-order-by.png create mode 100644 pictures/hive-right-join.png create mode 100644 pictures/sql-join.jpg create mode 100644 resources/dept.txt diff --git a/README.md b/README.md index c383d6b..ec82e1f 100644 --- a/README.md +++ b/README.md @@ -60,13 +60,14 @@ 1. [数据仓库Hive简介](https://github.com/heibaiying/BigData-Notes/blob/master/notes/Hive.md) 2. [Linux环境下Hive的安装部署](https://github.com/heibaiying/BigData-Notes/blob/master/notes/installation/Linux%E7%8E%AF%E5%A2%83%E4%B8%8BHive%E7%9A%84%E5%AE%89%E8%A3%85%E9%83%A8%E7%BD%B2.md) -3. [Hive Shell基本使用](https://github.com/heibaiying/BigData-Notes/blob/master/notes/HiveShell基本使用.md) -4. [Hive 核心概念讲解](https://github.com/heibaiying/BigData-Notes/blob/master/notes/Hive核心概念讲解.md) -5. [Hive 分区表和分桶表](https://github.com/heibaiying/BigData-Notes/blob/master/notes/Hive分区表和分桶表.md) +3. 连接Hive的三种方式 +4. [Hive Shell基本使用](https://github.com/heibaiying/BigData-Notes/blob/master/notes/HiveShell基本使用.md) +5. [Hive 核心概念讲解](https://github.com/heibaiying/BigData-Notes/blob/master/notes/Hive核心概念讲解.md) 6. [Hive 常用DDL操作](https://github.com/heibaiying/BigData-Notes/blob/master/notes/Hive常用DDL操作.md) -7. Hive 数据查询 -8. Hive 视图和索引 -9. Hive 模式设计 +7. [Hive 分区表和分桶表](https://github.com/heibaiying/BigData-Notes/blob/master/notes/Hive分区表和分桶表.md) +8. [Hive 视图和索引](https://github.com/heibaiying/BigData-Notes/blob/master/notes/Hive数据查询详解.md) +9. [Hive常用DML操作](https://github.com/heibaiying/BigData-Notes/blob/master/notes/Hive常用DML操作.md) +10. [Hive 数据查询详解](https://github.com/heibaiying/BigData-Notes/blob/master/notes/Hive数据查询详解.md) ## 三、Spark diff --git a/notes/Hive常用DML操作.md b/notes/Hive常用DML操作.md index 35d789a..7f6d039 100644 --- a/notes/Hive常用DML操作.md +++ b/notes/Hive常用DML操作.md @@ -16,7 +16,8 @@ 将文件数据加载到表时,Hive不会进行任何转换,加载操作是纯复制/移动操作,它将数据文件移动到Hive表定义的存储位置。 ```shell -LOAD DATA [LOCAL] INPATH 'filepath' [OVERWRITE] INTO TABLE tablename [PARTITION (partcol1=val1, partcol2=val2 ...)] +LOAD DATA [LOCAL] INPATH 'filepath' [OVERWRITE] +INTO TABLE tablename [PARTITION (partcol1=val1, partcol2=val2 ...)] ``` - Load 关键字代表从本地文件系统加载文件,省略则代表从HDFS上加载文件: @@ -74,8 +75,11 @@ LOAD DATA INPATH "hdfs://hadoop001:8020/mydir/emp.txt" OVERWRITE INTO TABLE emp ### 2.1 语法 ```sql -INSERT OVERWRITE TABLE tablename1 [PARTITION (partcol1=val1, partcol2=val2 ...) [IF NOT EXISTS]] select_statement1 FROM from_statement; -INSERT INTO TABLE tablename1 [PARTITION (partcol1=val1, partcol2=val2 ...)] select_statement1 FROM from_statement; +INSERT OVERWRITE TABLE tablename1 [PARTITION (partcol1=val1, partcol2=val2 ...) + [IF NOT EXISTS]] select_statement1 FROM from_statement; + +INSERT INTO TABLE tablename1 [PARTITION (partcol1=val1, partcol2=val2 ...)] + select_statement1 FROM from_statement; ``` + Hive 0.13.0开始,建表时可以通过使用TBLPROPERTIES(“immutable”=“true”)来创建不可变表(immutable table) ,如果不可以变表中存在数据,则INSERT INTO失败。(注:INSERT OVERWRITE的语句不受`immutable`属性的影响); @@ -90,7 +94,8 @@ INSERT INTO TABLE tablename1 [PARTITION (partcol1=val1, partcol2=val2 ...)] sele ```sql FROM from_statement - INSERT OVERWRITE TABLE tablename1 [PARTITION (partcol1=val1, partcol2=val2 ...) [IF NOT EXISTS]] select_statement1 + INSERT OVERWRITE TABLE tablename1 + [PARTITION (partcol1=val1, partcol2=val2 ...) [IF NOT EXISTS]] select_statement1 [INSERT OVERWRITE TABLE tablename2 [PARTITION ... [IF NOT EXISTS]] select_statement2] [INSERT INTO TABLE tablename2 [PARTITION ...] select_statement2] ...; ``` @@ -98,8 +103,11 @@ INSERT INTO TABLE tablename1 [PARTITION (partcol1=val1, partcol2=val2 ...)] sele ### 2.2 动态插入分区 ```sql -INSERT OVERWRITE TABLE tablename PARTITION (partcol1[=val1], partcol2[=val2] ...) select_statement FROM from_statement; -INSERT INTO TABLE tablename PARTITION (partcol1[=val1], partcol2[=val2] ...) select_statement FROM from_statement; +INSERT OVERWRITE TABLE tablename PARTITION (partcol1[=val1], partcol2[=val2] ...) +select_statement FROM from_statement; + +INSERT INTO TABLE tablename PARTITION (partcol1[=val1], partcol2[=val2] ...) +select_statement FROM from_statement; ``` 在向分区表插入数据时候,分区列名是必须的,但是列值是可选的。如果给出了分区列值,我们将其称为静态分区,否则它是动态分区。动态分区列必须在SELECT语句的列中最后指定,并且与它们在PARTITION()子句中出现的顺序相同。 @@ -146,7 +154,8 @@ TRUNCATE TABLE emp_ptn; 3. 静态分区演示:从`emp`表中查询部门编号为20的员工数据,并插入`emp_ptn`表中,语句如下: ```sql -INSERT OVERWRITE TABLE emp_ptn PARTITION (deptno=20) SELECT empno,ename,job,mgr,hiredate,sal,comm FROM emp WHERE deptno=20; +INSERT OVERWRITE TABLE emp_ptn PARTITION (deptno=20) +SELECT empno,ename,job,mgr,hiredate,sal,comm FROM emp WHERE deptno=20; ``` 完成后`emp_ptn`表中数据如下: @@ -160,7 +169,8 @@ INSERT OVERWRITE TABLE emp_ptn PARTITION (deptno=20) SELECT empno,ename,job,mgr, set hive.exec.dynamic.partition.mode=nonstrict; -- 动态分区 此时查询语句的最后一列为动态分区列,即deptno -INSERT OVERWRITE TABLE emp_ptn PARTITION (deptno) SELECT empno,ename,job,mgr,hiredate,sal,comm,deptno FROM emp WHERE deptno=30; +INSERT OVERWRITE TABLE emp_ptn PARTITION (deptno) +SELECT empno,ename,job,mgr,hiredate,sal,comm,deptno FROM emp WHERE deptno=30; ``` 完成后`emp_ptn`表中数据如下: @@ -172,7 +182,8 @@ INSERT OVERWRITE TABLE emp_ptn PARTITION (deptno) SELECT empno,ename,job,mgr,hir ## 三、使用SQL语句插入值 ```sql -INSERT INTO TABLE tablename [PARTITION (partcol1[=val1], partcol2[=val2] ...)] VALUES ( value [, value ...] ) +INSERT INTO TABLE tablename [PARTITION (partcol1[=val1], partcol2[=val2] ...)] +VALUES ( value [, value ...] ) ``` + 使用时必须为表中的每个列都提供值。不支持只向部分列插入值(可以为缺省值的列提供空值来消除这个弊端); diff --git a/notes/Hive数据查询详解.md b/notes/Hive数据查询详解.md new file mode 100644 index 0000000..25b7ce5 --- /dev/null +++ b/notes/Hive数据查询详解.md @@ -0,0 +1,407 @@ +# Hive数据查询详解 + + + + + +## 一、数据准备 + +为了演示查询操作,这里需要预先创建两张表,并加载数据。 + +> 这里的表结构主要参考自Oracle内置的练习表——emp表和dept表,涉及到数据文件emp.txt和dept.txt可以在本仓库的sources目录下下载。 + +### 1.1 员工表 + +```sql + -- 建表语句 + 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 部门表 + +```sql + -- 建表语句 + 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 分区表 + +这里需要额外创建一张分区表,主要是为了演示分区查询: + +```sql +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 + +```sql +-- 查询表中全部数据 +SELECT * FROM emp; +``` + + + +### 2.2 WHERE + +```sql +-- 查询10号部门中员工编号大于 7782 的员工信息 +SELECT * FROM emp WHERE empno > 7782 AND deptno = 10; +``` + + + +### 2.3 DISTINCT + +Hive支持使用DISTINCT关键字去重。 + +```sql +-- 查询所有工作类型 +SELECT DISTINCT job FROM emp; +``` + + + +### 2.4 分区查询 + +分区查询(Partition Based Queries),可以指定某个分区或者分区范围。 + +```sql +-- 查询分区表中部门编号在[20,40]之间的员工 +SELECT emp_ptn.* FROM emp_ptn +WHERE emp_ptn.deptno >= 20 AND emp_ptn.deptno <= 40; +``` + + + +### 2.5 LIMIT + +```sql +-- 查询薪资最高的5名员工 +SELECT * FROM emp ORDER BY sal DESC LIMIT 5; +``` + + + +### 2.6 GROUP BY + +Hive支持使用GROUP BY进行分组聚合操作。 + +```sql +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 ,也就是非严格模式。 + +```sql +-- 查询员工工资,结果按照部门升序,按照工资降序排列 +SELECT empno, deptno, sal FROM emp ORDER BY deptno ASC, sal DESC; +``` + + + +### 2.8 HAVING + +可以使用HAVING对分组数据进行过滤。 + +```sql +-- 查询工资总和大于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上进行处理: + +```properties +k1 +k2 +k4 +k3 +k1 +``` + +Reducer1得到如下乱序数据: + +```properties +k1 +k2 +k1 +``` + + +Reducer2得到数据如下: + +```properties +k4 +k3 +``` + +如果想让Reducer上的数据时有序的,可以结合`SORT BY`使用(示例如下),或者使用下面我们将要介绍的CLUSTER BY。 + +```sql +-- 将数据按照部门分发到对应的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`可以保证数据在全局是有序的。 + +```sql +SELECT empno, deptno, sal FROM emp CLUSTER BY deptno ; +``` + + + +## 三、多表联结查询 + +Hive支持内连接,外连接,左外连接,右外连接,笛卡尔连接,这和传统数据库中的概念一致。关于以上概念,可以参见下图。 + +需要特别强调:JOIN语句的关联条件必须用ON指定,不能用WHERE指定,否则就会先做笛卡尔积,再过滤,这会导致你得不到预期的结果(下面的演示会有说明)。 + +
x(A9gG{36z)THVrYIcc{>61F3{UsLM_!!qFcvYf$wgH*W
zQHT>ANM=iHpwP082FH`93)r8&1em5FMZ#qI#KA9lq{rpPq$bp7E-6%~1{h;)|DsAV
z4uwPSct0ldx{h1J33xCq{_QZIDv%kAKis6bby@L2fLS}^$933y8N`Ku3C)?mg{B>#
z>_%#>{s%Ef&|j92%iFqWh3N%}*K94(>YIoM3pOjw2}nwPXg!&@)(t_sBtZXX_}uj%
zjsC-(!}Nd4MuyAEc8Mt$%0b70aU9D4YHtO*PKYafXRfsVoR2*FRo )SWEE`1+rcDtjOL0P_=B%~#J2?}RntDc|-suV|$
zxU5K4_$OWqCZ->kyb~+t4PRiJwCCkqm$v;ii^uqA#k >#SHmg
z(Yw7G;g1(JR^SUfiB`ojskn-ojagn((_4~7nu0ni%51I671FwX;Q@cfgHjEL$XkDa
zetd00({xo%rC6Okj(s{2Q9sl|=GMQR+vueCn851cT8tdCZh|M>BY@c-Tt?z*|KH&J|9Z#B#8JueU|{4C+C5_iD3O9H2U
zBPdDtCP#7*Lrl3$rJusi*dlmEQh(Y`$bqKlBJBl@n4W$$L9`xb{$71_lm8`FvL3H;
zducyOu?GHLf6!c>9eLSgJ}{h06;(Uqw)M%v9F2oK()^YrxRO55JfgZq-0=ucyqbUu
znp>dUPa*lif!x9ML(j;Je+k^!#suEG
Xd{8I-ta
zHbWa0TOMrnx`N
gwXYA
zawHYgr~TMBqQVc@#kMipx&G1u_DCL8)vXTknuF-wbg%1S1GGe@@^QKFqrBe<{BF&+
zawa}XxEuK9w^H0&hELB=y-w~HkbSfl(?C&s#A)lV5W5p>R)H!+oHh+x!O@b8@f>FJ
zaS3v#1ea>sea-DC%jxUi2O;WU0YQTDVoCx$R
G&grB&u~oo~I|Z7u$psc~^;gRc<(H
z#Qv6X(6@Ymm#rhLt)~{qn9TSFSkF`CN~Ed-UW2ST{YWx`Fmwl`KC%6l*KX+Av}ZbR
z;RtTW?sdN1%#xaa;mXJ%{IWM4^k%+M5c3q}HH{>rH1sF+XwkC1Ice)>Y0+rPyaCXO
zk&J`GhfHAqm|Q~K&e&0H%=fnefZIIw|8v~mn4yZWf~}t>0gy`yB!4@ejwnf8J<1+k
zax)9{YICcLGsMkyko&AR*`pZqA6s3<4B4YgxLxo;2@i|6#FrYgWfwU{)xTIJd4=K-
zc6-oQKvdjSn0A7*SWX@(oKl_tb@HWXinyA#7DH*8l`?(y1kt|56at)%+g4r67dL>+01-*;rqwpjo^sy1sHQMlk
z_dda}ZA0_>4h?+-=m&drof0y?xcbInZQqilW}PIa8LG7<=ByOCI4)7_G%qG|ZCx9_
zas=6e;Ukcsw`(eeQaL|=Nqx;^o)aTp%=Q>9Xm=Q#FudS=sXP)1+aH&<$QNWZYD88F
z#W~;cR;9ns7YYwMFY$#7*T(X;gIMrpt6K2~lqCd%1Nr-TFi
zUKG1-ER3xRF=*?S?{3n!%CLj{NalNOeOiApV#Q+bZ`^YJC}5it)v5cd4REC^u(Mxn
z)?0S3