大数据笔记--Hive(第四篇)
作者:互联网
目录
一、join
1、概述
在Hive中,同MySQL一样,提供了多表的连接查询,并且支持left join,right join,inner join,full outer join以及笛卡尔积查询
在连接查询的时候,如果不指定,那么默认使用的是inner join
在Hive中,除了支持上述比较常用的join以外,还支持left semi join。当a left semi join b的时候,表示获取a表中的数据哪些在b表中出现过
下图是mysql的join图解,供参考:
2、案例
首先我们在hdfs上创建两个目录orders和products
hadoop fs -mkdir /orders
hadoop fs -mkdir /products
然后将我们本地创建两个txt文件,分别上传到hdfs上
vim order.txt
1001 20210710 4 2 1002 20210710 3 100 1003 20210710 2 40 1004 20210711 2 23 1005 20210711 4 55 1006 20210823 3 20 1007 20210823 2 3 1008 20210823 4 23 1009 20210912 2 10 1010 20210912 2 2 1011 20210914 3 14 1012 20210914 3 18
vim products.txt
1 chuizi 3999 2 huawei 3999 3 xiaomi 2999 4 apple 5999
hadoop fs -put /home/data/order.txt /orders/
hadoop fs -put /home/data/products.txt /products/
建表语句:
create external table orders (orderid int, orderdate string, productid int, num int) row format delimited fields terminated by ' 'location '/orders';
create external table products (productid int, name string, price double) row format delimited fields terminated by ' ' location '/products';
左连接-以左表为准:
select * from orders o left join products p on o.productid = p.productid;
右连接-以右表为准:
select * from orders o right join products p on o.productid = p.productid;
内连接 - 获取两个表都有的数据:
select * from orders o inner join products p on o.productid = p.productid;
全外连接:
select * from orders o full outer join products p on o.productid = p.productid;
笛卡尔积:
select * from orders, products;
需求一:获取每一天卖了多少钱:
select o.orderdate, sum(o.num * p.price) from orders o inner join products p on o.productid = p.productid group by o.orderdate;
需求二:查询哪些商品被卖出去过 - 实际上就是获取商品表中的哪些数据在订单表中出现过
select * from products p left semi join orders o on p.productid = o.productid;
二、查询和排序
1、having
在Hive中,where可以针对字段来进行条件查询,但是where无法针对聚合结果进行条件查询;如果需要对聚合结果进行条件查询,那么此时需要使用having
案例:
原始数据:
1 Apollo 4900 1 Billy 5100 1 Cary 4800 1 Dylan 5000 1 Ford 4700 2 Apollo 5300 2 Billy 4600 2 Cary 4700 2 Dylan 5100 2 Ford 4500 3 Apollo 5200 3 Billy 4300 3 Cary 4600 3 Dylan 5200 3 Ford 4800
建表语句:
create table salaries (month int, name string, salary double) row format delimited fields terminated by ' ';
加载数据:
load data local inpath '/home/data/salaries.txt' into table salaries;
获取平均工资超过5000的员工:
select name, avg(salary) as avgsalary from salaries group by name having avgsalary > 5000;
或者使用子查询:
select * from (select name, avg(salary) as avgsalary from salaries group by name)tmp where avgsalary > 5000;
2、排序
①、在Hive中,提供了2种排序方式
order by:在排序的时候忽略掉ReduceTask的个数,会将所有的数据进行统一的排序
sort by:在排序的时候会按照ReduceTask的个数产生对应数量的结果文件。在每一个结果文件内部进行排序。在sort by的时候如果不指定,那么会根据排序数据的哈希码来分配到多个不同的文件中
②、sort by经常结合distribute by来使用,其中利用distribute by对数据进行分类,然后再在每一个分类中对数据进行排序
③、如果distribute by和sort by的字段一致,那么可以写成cluster by
④、案例
原始数据:
1 Max 69 1 Eric 70 1 Hank 95 1 Larry 82 2 Justin 74 2 Tim 79 2 Ken 81 2 Ivan 87 3 Nick 95 3 Leo 72 3 Mars 84 3 Reed 91
建表语句:
create table students(class int, name string, score int) row format delimited fields terminated by ' ';
加载数据:
load data local inpath '/home/data/students.txt' into table students;
Hive底层会将SQL转化为MapReduce,如果不指定,则只有1个ReduceTask
1个ReduceTask-> order by
我们将数据放到本地目录下查看
insert overwrite local directory '/home/orderby1' row format delimited fields terminated by ' ' select * from students order by score desc;
1个ReduceTask -> sort by
再次放到本地路径下查看数据:
insert overwrite local directory '/home/sortby' row format delimited fields terminated by ' ' select * from students sort by score desc;
在只有一个ReduceTask的前提下,order by和sort by的排序结果一致
设置ReduceTask的数量:
set mapred.reduce.tasks = 3;
多个ReduceTask -> order by
再次执行放到本地
insert overwrite local directory '/home/orderby2' row format delimited fields terminated by ' ' select * from students order by score desc;
多个ReduceTask -> sort by
insert overwrite local directory '/home/sortby2' row format delimited fields terminated by ' ' select * from students sort by score desc;
这时候会发现在多个ReduceTask的情况下,sort by 会生成多个结果文件
按班级来分别对学生的成绩排序:
insert overwrite local directory '/home/distributeby' row format delimited fields terminated by ' ' select * from students distribute by class sort by score desc;
如果distribute by和sort by的字段一致,那么可以替换为cluster by:
insert overwrite local directory '/home/distributeby2' row format delimited fields terminated by ' ' select * from students distribute by score sort by score;
等价于:
insert overwrite local directory '/home/clusterby' row format delimited fields terminated by ' ' select * from students cluster by score;
三、beeline
1、概述
beeline是Hive提供的一个远程连接的工具,允许用户去远程连接指定节点上的Hive服务
beeline底层实际上是利用了JDBC的方式来发起了连接
需要注意的是,beeline在连接过程中可能会受到hadoop的权限验证的阻拦,所以在启动beeline之前,还需要去更改Hadoop的一部分配置
2、步骤
①、关闭Hadoop
stop-all.sh
②、关闭所有的Hive进程RunJar
kill -9 RunJar的进程号
③、编辑Hadoop的配置文件
vim /home/software/hadoop-3.1.3/etc/hadoop/core-site.xml
添加如下配置:
<property> <name>hadoop.proxyuser.root.hosts</name> <value>*</value> </property> <property> <name>hadoop.proxyuser.root.groups</name> <value>*</value> </property>
④、重新启动hadoop与Hive
start-all.sh
hive --service metastore &
hive --service hiveserver2 &
⑤、启动beeline
beeline -u jdbc:hive2://hadoop01:10000/demo -n root
四、文件格式
1、概述
Hive中的数据最终会以文件的形式落地到HDFS上,因此Hive落地的文件存在不同的存储格式,其中最主要的存储格式有4种:textfile,sequencefile,orc和parquet
textfile和sequencefile底层采用的是行存储方式,orc和parquet采用的是列存储方式
在Hive中,如果不指定,则默认采用的是textfile格式
2、orc
①、orc格式是Hive0.11开始引入的一种存储格式,采取的列存储方式
②、在每一个orc格式文件中,包含1个多个Stripe,1个File Footer以及1个Postscript
1、Stripe用于orc文件的数据存储数据
①、默认情况下,Stripe和Block一样的
②、每一个Stripe中包含3部分:Index Data,Row Data,Stripe Footer
Ⅰ、Index Data:用于记录索引,默认情况下,在Stripe中每一万条数据建立一个 索引,索引记录这一行数据在各个列中的offset(偏移量)
Ⅱ、Row Data:存储数据。在添加数据的时候,往往是按行添加的。在获取到一行数据之后,会将这行数据的每一个字段拆分出来,拆分之后按照列的形式来进行存储。在存储的时候,可以给不同的列执行不同的编码形式,编码之后会将这一列封装成一个或者多个Stream来进行存储。因为同一个列的字段类型是一样的,所以可以针对每一个列采取更好的压缩机制
Ⅲ、Stripe Footer:存储每一个Stream的类型、长度等信息
2、File Footer:用于记录每一个Stripe中存储的数据的行数等信息
3、Postscript:记录文件是否进行了压缩以及压缩编码等信息,还记录了File Footer在文件中的起始位置
③、在读取orc文件的时候,首先通过Postscript来获取File Footer的位置,再通过File Footer来获取Stream的位置,最后来读取Stream中的数据
注意:建表的时候在后面加上 stored as orc 就可以设置orc格式了。
五、基本架构
①、Client Interface:提供给用户用于操作Hive的接口,主要有3种:CLI(command-line interface,命令行接口),JDBC/ODBC(用Java代码操作Hive),WEBUI(WEB界面,通过浏览器页面来访问)
②、Metastore:用于存储Hive的元数据的。如果不指定,Hive的元数据是维系在Derby。当操作Hive的时候,都会先访问Metastore来进行元数据的校验
③、Driver:驱动器,包含了四个部分
SQL Parser:SQL解析器,解析SQL语句,生成对应的抽象语法树AST
Physical Plan:编译器,会将抽象语法树编译成要执行的逻辑计划
Query Optimizer:优化器,会对逻辑计划进行优化
Execution:将逻辑计划转化为物理计划,例如转化为MapReduce程序
④、MapReduce:Execution产生程序之后,现阶段会交给MapReduce来执行
⑤、HDFS:存储Hive中的数据
六、优化
1、Fetch值修改
①、在Hive中,可以通过hive.fetch.task.conversion属性来修改fetch的状态。在Hive3.X中,这个属性的默认值是more,在之前的版本中,这个属性的默认值是minimal
②、如果将这个属性的值改为none,那么Hive进行的所有的操作都会转为MapReduce程序,那么会导致部分操作的效率降低,例如select * from person;这个SQL是查询整表,实际上就是将文件从头到尾顺次读取,此时这个操作可以不适用MapReduce
2、map side join
①、开启之后,在大表和小表进行join的时候,会自动的将小表中的数据放到内存中,然后在处理大表数据的过程中,如果用到了小表中的数据,那么会自动的从内存中来读取小表的数据而不是再从磁盘上来读取,利用这种方式能够相对有效的提高执行效率
②、小表的大小可以通过属性hive.mapjoin.smalltable.filesize来调节,默认值是25MB
③、可以通过hive.auto.convert.join属性来开启map side join,默认值是true
④、在Hive3.X之前,要求必须是小表join大表才会触发这个map side join;但是注意,从Hive3.X开始,不再要求小表的位置
3、启用严格模式
①、将hive.strict.checks.no.partition.filter设置为true之后,要求在查询分区表的时候必须携带分区字段
②、将hive.strict.checks.orderby.no.limit设置为true之后,要求在对数据排序的时候必须添加limit字段
③、将hive.strict.checks.cartesian.product设置true之后,要求查询结果中不准出现笛卡尔积
4、JVM重用
①、Hive会将SQL在底层转化为MapReduce来执行,MapReduce在执行的时候会拆分为MapTask和ReduceTask。NodeManager在执行任务的时候,会在本节点上来开启一个JVM子进程执行MapTask或者ReduceTask。默认情况下,每一个JVM子进程只执行一个子任务就会结束,所以如果存在多个子任务就需要开启和关闭多次JVM子进程
②、通过属性mapred.job.reuse.jvm.num.tasks来调节,默认为1,一般来说我们调节到9或10
标签:sort,join,--,Hive,products,第四篇,select,productid 来源: https://blog.csdn.net/weixin_45895096/article/details/123515446