一、准备案例数据
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