Hive控制台、交互命令的使用、shell执行hql脚本、定时任务设定

一、准备案例数据

1.1、数据

[hdp@hdp02 demo]$ vi emp.txt
7369	SMITH	CLERK	7902	1980-12-17 00:00:00	800.00		20
7499	ALLEN	SALESMAN	7698	1981-02-20 00:00:00	1600.00	300.00	30
7521	WARD	SALESMAN	7698	1981-02-22 00:00:00	1250.00	500.00	30
7566	JONES	MANAGER	7839	1981-04-02 00:00:00	2975.00		20
7654	MARTIN	SALESMAN	7698	1981-09-28 00:00:00	1250.00	1400.00	30
7698	BLAKE	MANAGER	7839	1981-05-01 00:00:00	2850.00		30
7782	CLARK	MANAGER	7839	1981-06-09 00:00:00	2450.00		10
7788	SCOTT	ANALYST	7566	1987-04-19 00:00:00	1500.00		20
7839	KING	PRESIDENT		1981-11-17 00:00:00	5000.00		10
7844	TURNER	SALESMAN	7698	1981-09-08 00:00:00	1500.00	0.00	30
7876	ADAMS	CLERK	7788	1987-05-23 00:00:00	1100.00		20
7900	JAMES	CLERK	7698	1981-12-03 00:00:00	950.00		30
7902	FORD	ANALYST	7566	1981-12-03 00:00:00	3000.00		20
7934	MILLER	CLERK	7782	1982-01-23 00:00:00	1300.00		10
[hdp@hdp02 demo]$ vi dept.txt
10	ACCOUNTING	NEW YORK
20	RESEARCH	DALLAS
30	SALES	CHICAGO
40	OPERATIONS	BOSTON

1.2、上传数据到hdfs上的emp_dept目录下

[hdp@hdp02 ~]$ hdfs dfs -mkdir /emp
[hdp@hdp02 ~]$ hdfs dfs -mkdir /dept
[hdp@hdp02 ~]$ hdfs dfs -put /home/hdp/demo/dept.txt /dept/dept.txt                  
[hdp@hdp02 ~]$ hdfs dfs -put /home/hdp/demo/emp.txt /emp/emp.txt 
[hdp@hdp02 demo]$ hdfs dfs -cat /dept/dept.txt
[hdp@hdp02 demo]$ hdfs dfs -cat /emp/emp.txt

二、hive控制台执行创建表

2.1、创建hive的两个外部表

hive (hive01)> create external table emp
(empno INT comment "-员工表编号",  
 ename STRING comment '员工姓名', 
 job STRING comment '职位类型', 
 mgr INT comment '领导编号' ,  
 hiredate TIMESTAMP comment '雇佣日期',   
 sal DECIMAL(7,2) comment '工资',    
 comm DECIMAL(7,2) comment '奖金',    
 deptno INT comment '部门编号' ) 
 row format delimited fields terminated by "\t" 
 lines terminated by "\n"
 location "/emp";
hive (hive01)> create external table dept
(deptno INT comment '部门编号',
 dname STRING comment '部门名称',
 loc STRING comment '部门所在的城市' ) 
 row format delimited fields terminated by "\t" 
 lines terminated by "\n"
 location "/dept";
hive (hive01)> select * from dept;
hive (hive01)> select * from emp;

2.2、创建一个emp_ptn动态分区表

-- 动态分区表
      -- 开启动态分区
hive (hive01)> set hive.exec.dynamic.partition = true;
hive (hive01)> set hive.exec.dynamic.partition.mode = nonstrict;
      -- 创建分区表
hive (hive01)> 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";
      -- 往分区表导入数据,注意分区字段放在最后
hive (hive01)> insert into table emp_ptn partition(deptno)
      select empno,ename,job,mgr,hiredate,sal,comm,deptno from emp;
hive (hive01)> show partitions emp_ptn; -- 查看分区

三、Hive的DQL数据查询(使用交互命令)

3.1、注意:hive的select ...不支持以下类型

  • 1、非等值连接
  • 2、or类型的多条件连接
  • 3、默认情况下笛卡尔积不支持

3.2、hive -e :不进入hive的交互窗口执行sql语句

3.2.1、查询 10 号部门中员工编号大于 7782 的员工信息,保存到demo01.txt文件;

[hdp@hdp02 ~]$ mkdir hive_select;
[hdp@hdp02 ~]$ hive -e "select * from hive01.emp_ptn where deptno = 10 and empno > 7782;" > /home/hdp/hive_select/demo01.txt
[hdp@hdp02 ~]$ less /home/hdp/hive_select/demo01.txt

3.2.2、查询所有工作类型

[hdp@hdp02 ~]$ hive -e "select distinct job from hive01.emp;" > /home/hdp/hive_select/job.txt
[hdp@hdp02 ~]$ less /home/hdp/hive_select/job.txt

3.2.3、查询分区表中部门编号在[20,30]之间的员工(不用全表扫描,会快很多)

[hdp@hdp02 ~]$ hive -e "select emp_ptn.* from hive01.emp_ptn where emp_ptn.deptno >=20 and emp_ptn.deptno <=30;"  >  /home/hdp/hive_select/demo02.txt
[hdp@hdp02 ~]$ more /home/hdp/hive_select/demo02.txt 

3.3、hive -f :不进入hive的交互窗口执行保存了sql语句的文件

3.3.1、查询各个部门总人数、薪酬总和及部门平均薪资,保存到sal01.txt文件

[hdp@hdp02 hive_select]$ vim sal.txt
select deptno,count(empno) c,sum(sal) s ,avg(sal) avg_s from hive01.emp group by deptno;

[hdp@hdp02 hive_select]$ hive -f /home/hdp/hive_select/sal.txt > /home/hdp/hive_select/sal01.txt
[hdp@hdp02 hive_select]$ cat /home/hdp/hive_select/sal01.txt

3.3.2、查询工资总和大于 9000 的所有部门名称及合计薪资

[hdp@hdp02 hive_select]$ vim sal_m.txt
select d.dname,e.s from hive01.dept  d inner join
(select deptno,sum(sal) s  from hive01.emp group by deptno having sum(sal)>9000) e
on d.deptno=e.deptno;

[hdp@hdp02 hive_select]$ hive -f /home/hdp/hive_select/sal_m.txt > /home/hdp/hive_select/sal02.txt
[hdp@hdp02 hive_select]$ cat /home/hdp/hive_select/sal02.txt

3.3.3、统计每个职位有多少个员工,并且按照数量从大到小排序

[hdp@hdp02 hive_select]$ vim job_c.txt
select job,count(distinct empno) c from hive01.emp 
group by job order by c desc;

[hdp@hdp02 hive_select]$ hive -f /home/hdp/hive_select/job_c.txt > /home/hdp/hive_select/job_c01.txt
[hdp@hdp02 hive_select]$ cat /home/hdp/hive_select/job_c01.txt

四、shell执行hql脚本

注意:hive -e " 不能换行后再使用 " 号

4.1、统计出每个岗位的最高工资、最低工资和平均工资,使用hive -e模式

[hdp@hdp02 hive_select]$ vim job_s.sh
#! bin/bash
hive -e "select job, max(sal) s_max, min(sal) s_min, round(avg(sal),2) s_avg 
from hive01.emp
group by job 
order by s_avg desc;" > /home/hdp/hive_select/job_s01.txt

[hdp@hdp02 hive_select]$ chmod +x /home/hdp/hive_select/job_s.sh
[hdp@hdp02 hive_select]$ sh job_s.sh
[hdp@hdp02 hive_select]$ cat job_s01.txt

4.2、查询出每个地区工资最高的员工

使用hive -e模式,在查询语句字符串中插入变量 ${变量名},在shell脚本中不能混用hive定义变量的方式

[hdp@hdp02 hive_select]$ vim loc_s.sh     
#! /bin/bash

tabname01="hive01.emp" #等号两边不能有空格
tabname02="hive01.dept"

hive -e "
select a.loc,emp.* from 
(select /*+ STREAMTABLE(e) */ 
 d.loc loc, d.deptno deptno, max(e.sal) m_sal 
 from ${tabname02} d inner join ${tabname01} e 
 on d.deptno=e.deptno 
 group by  d.loc,d.deptno) a
join hive01.emp on a.deptno=emp.deptno 
and emp.sal=a.m_sal;" > /home/hdp/hive_select/loc_s01.txt
[hdp@hdp02 hive_select]$ chmod +x loc_s.sh 
[hdp@hdp02 hive_select]$ sh loc_s.sh 
[hdp@hdp02 hive_select]$ cat loc_s01.txt

4.3、shell调用执行sql脚本,查询上半年入职员工最多的部门,

[hdp@hdp02 hive_select]$ vim c_d.sql
select deptno,
count(substr(hiredate,6,2)) m
from hive01.emp
where substr(hiredate,6,2)<=6
  oup by deptno
order by m desc
limit 1;
[hdp@hdp02 hive_select]$ vim c_d.sh
#! /bin/bash/
hive -f /home/hdp/hive_select/c_d.sql > /home/hdp/hive_select/c_d.txt
[hdp@hdp02 hive_select]$ chmod +x c_d.sql
[hdp@hdp02 hive_select]$ chmod +x c_d.sh 
[hdp@hdp02 hive_select]$ sh c_d.sh
[hdp@hdp02 hive_select]$ cat c_d.txt

4.4、开启本地模式(提高小数据集的查询速度)

开启本地模式后,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 操作的查询,你会发现速度会有显著的提升。

[hdp@hdp02 hive_select]$ vim loc_n.sh
#! /bin/bash/
hive -e "
SET hive.exec.mode.local.auto=true; -- 开启本地模式

-- 查询在纽约办公的所有员工信息

SELECT e.*  FROM hive01.emp e
LEFT SEMI JOIN hive01.dept d 
ON e.deptno = d.deptno AND d.loc='NEW YORK';

--上面的语句就等价于

SELECT e.* FROM  hive01.emp e
WHERE e.deptno IN (
SELECT d.deptno FROM hive01.dept d WHERE d.loc='NEW YORK');
" > /home/hdp/hive_select/loc_n.txt
[hdp@hdp02 hive_select]$ chmod +x loc_n.sh 
[hdp@hdp02 hive_select]$ sh loc_n.sh 
[hdp@hdp02 hive_select]$ cat /home/hdp/hive_select/loc_n.txt

4.5、join连接查询注意事项(减少数据倾斜)

优化过程:假定查询的最后一个表是最大的一个表,在对每行记录进行 JOIN 操作时,它将尝试将其他的表缓存起来,然后扫描最后那个表进行计算。如果所有表中只有一张表是小表,那么 Hive 把这张小表加载到内存中。这时候程序会在 map 阶段直接拿另外一个表的数据和内存中表数据做匹配,由于在 map 就进行了 JOIN 操作,从而可以省略 reduce 过程,这样效率可以提升很多。

  • 用户需要保证查询的表的大小从左到右是依次增加的(先小表后大表);
  • 当最大表没有放在最后面时,加入select /*+ STREAMTABLE(e) */....from e join d...  标志即可,注意后面没逗号;
  • 当最小表没有放在最前面时,加入select /*+ MAPJOIN(d) */  ...from e join d ...   标志即可,注意后面没逗号。
  • 策略:1.最好连接表时就尽量顺序;2.一个大表其他都是小表时标志大表,反之一个小表对多个小表时标记小表。
[hdp@hdp02 hive_select]$ vim loc_n.sh
#! /bin/bash/
hive -e "
SET hive.exec.mode.local.auto=true; -- 开启本地模式

-- 查询在纽约办公的所有员工信息
SELECT /*+ STREAMTABLE(e) */ e.*  FROM hive01.emp e
LEFT SEMI JOIN hive01.dept d 
ON e.deptno = d.deptno AND d.loc='NEW YORK';

-- 或者
SELECT /*+ MAPJOIN(d) */ e.*  FROM hive01.emp e
LEFT SEMI JOIN hive01.dept d 
ON e.deptno = d.deptno AND d.loc='NEW YORK';

--上面的语句就等价于,但效率更高
SELECT e.* FROM  hive01.emp e
WHERE e.deptno IN (
SELECT d.deptno FROM hive01.dept d WHERE d.loc='NEW YORK');
" > /home/hdp/hive_select/loc_n.txt
[hdp@hdp02 hive_select]$ chmod +x loc_n.sh
[hdp@hdp02 hive_select]$ sh loc_n.sh 
[hdp@hdp02 hive_select]$ cat loc_n.txt

五、定时执行hql的shell脚本

5.1、at定时器的使用:https://man.linuxde.net/at

在命令行输入at,然后指定执行的时间,在输入enter键换行,接下来输入要执行的任务,多任务继续输入enter键换行隔开。输入的任务完毕,此时按下ctrl+d,则会出现类似“at> <EOT>job 5 at 2020-03-05 18:01”,此时输入完毕。

[hdp@hdp02 hive_select]$ vim a.sh          
#! /bin/bash/

hive -e "
-- 查询job为clerk的员工信息
SELECT /*+ MAPJOIN(d) */ e.*,d.* 
FROM hive01.emp e JOIN hive01.dept d
ON e.deptno = d.deptno
WHERE job='CLERK';" > /home/hdp/hive_select/a.txt

hive -e "
-- 查询job为SALESMAN的员工信息
SELECT /*+ STREAMTABLE(e) */  e.*,d.* 
FROM hive01.emp e JOIN hive01.dept d
ON e.deptno = d.deptno
WHERE job='SALESMAN';" > /home/hdp/hive_select/b.txt
[hdp@hdp02 hive_select]$ chmod 777 a.sh          
[hdp@hdp02 hive_select]$ at now + 1 minutes
at> sh /home/hdp/hive_select/a.sh
at> <EOT>
job 7 at 2020-03-05 18:35
[hdp@hdp02 hive_select]$ atq
[hdp@hdp02 hive_select]$ cat a.txt
[hdp@hdp02 hive_select]$ cat b.txt

5.2、计划任务 crontab -e :https://blog.csdn.net/weixin_41685388/article/details/102531518

发布了133 篇原创文章 · 获赞 182 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/weixin_41685388/article/details/104698449