[大数据] HiveQL知识点

文章目录

        • Q1:什么是数据倾斜,怎么产生,怎么解决?
        • Q2:什么是hive的严格模式(strict mode)?
        • Q3:order by, sort by, distribute by, cluster by的区别?
        • Q4:collect_all()的作用?
        • Q5:三个排名函数的区别?
        • Q6:Hive原理
        • Q7:Hive存储元数据的方式?
        • Q8:Hive优化方法
        • Q9:什么时候可以用别名,什么时候不可以?
        • Q10:hive怎么确定mapper、reducer的个数?
        • Q11:分区、分桶、索引的区别?

Q1:什么是数据倾斜,怎么产生,怎么解决?

查询时,mapper的结果经过shuffle,按照key的hash来分配到不同的reducer上,如果分配不均匀,导致其中一个或几个reducer的运行时间过长,导致整个mapreducer完成得很慢,这就是数据倾斜。
  原因可能是,join、group by、count(distinct )的时候,key的值比较集中,导致这个值的大量数据全放到一个reducer里,如果这个key有大量null值,也导致数据倾斜;
  解决方法是:
  1. 增大reducer个数
  2. 设置负载平衡(会生成两个MR job,先后执行。第一个是随机分配到reducer,可以平衡负载,实现初步的聚合,减少后面的工作量。第二个按照key的hash取mod之后分配到reducer,完成最终的聚合)
  3. 小表join大表时,使用mapjoin,可以让小表存入内存,只在map端进行聚合。把小表写在前,大表写在后。
  4. 有大量null值时,把null值变成一个字符串加上随机数,反正join时关联不上,不会影响最终结果
  5. 需要实现count(distinct )的时候,先对key做group by,然后count(1)即可
  注意:对于count(),sum()这种可以由部分结果得到最终结果的聚合函数,方法2、3是有效的,但是对于avg(),mean()这种不能由部分结果得到最终结果的聚合函数,是无效的。
   [ 原理 ]

Q2:什么是hive的严格模式(strict mode)?

用来限制某些后果不好的查询,它们会消耗大量资源,包括:
  1. 如果表使用了分区,但是查询没有用where过滤分区
  2. 使用了order by,但是没有加limit限制
  3. 笛卡尔乘积,即join不用on而是用where的

Q3:order by, sort by, distribute by, cluster by的区别?

1. 使用order by的话,全局排序,所有数据最终在一个reducer里排序,耗时较多,在strict mode下,必须加limit限制,适用于数据量不太大的场景(不清楚加了limit之后是否影响结果???)
  2. 使用sort by的话,局部排序,数据分别在各自的reducer排序,不保证最终结果有序
  3. distribute by,在map端控制按照哪个字段的hash值分发给各个reducer,通常配合sort by使用,相当于分组排序,distribute by X sort by X相当于全局排序。适用于数据量比较大的排序场景,sort by一定要放在distrubute by后面。例如对于表

type price brand
noodle 1600 huafeng
bread 1231 meixin
noodle 1221 tongyi
beer 1432 zhujiang
select type, price, brand from store distribute by type sort by type asc, price asc

type相同的会放入同一个reducer,同一个reducer内按照type和price排序,相当于做了分组排序,结果如下

type price brand
beer 1432 zhujiang
bread 1231 meixin
noodle 1221 tongyi
noodle 1600 huafeng

4.cluster by相当于distribute by X sort by X,但是只能降序排列

Q4:collect_all()的作用?

属于一种聚合函数,与group by配合使用,可以把组内某个字段所有取值拿出来,作为新的字段。collect_set()、collect_list()作用类同。

Q5:三个排名函数的区别?

1. row_number()返回连续、不重复的排名,key相同时排名也不重复
  2. dens_rank()返回连续、重复的排名
  3. rank()返回不连续、重复的排名
  例如对于:3 3 4 5 5 6  
|排名函数|返回排名|
|:|:|
|row_number() |1 2 3 4 5 6 |
|dens_rank() |1 1 2 3 3 4 |
|rank() |1 1 3 4 4 6 |

Q6:Hive原理

hive是运行在hadoop之上的一个数据仓库框架,数据放在HDFS上,查询使用MapReduce来执行查询。它支持类似SQL的语言,它其实是个编译器,把SQL编译为MapReduc的作业。
  因为基于Hadoop,它拥有hadoop的所有优点和缺点。
  优点:
  使用类SQL语言,非常方便
  使用磁盘而不是内存,所以能处理海量数据,很适合处理大规模的离线数据分析处理。
  高容错性,自动备份数据,自动检测并回复故障。
  缺点:
  数据一词写入多次写出,因此已有的数据表不可更新。
  不能做到低延迟

Q7:Hive存储元数据的方式?

1. 存在内存derby存储,只能开一个客户端,不推荐
  2. 存在MySQL数据库,可以多客户端使用,推荐

Q8:Hive优化方法

1. join优化。小表放在join左边,大表放在join右边。因为join在reducer端时,左表会放入内存,所以小表最好放左边
  2. 少用order by优化。order by只在一个reducer内排序,太慢了。使用distribute by X sort by X也能达到全局排序。
  3. 尽早过滤数据,例如使用分区。
  4. 其他参考这篇,写得很好 [ 数据分析利器之hive优化十大原则 ]

Q9:什么时候可以用别名,什么时候不可以?

由于sql在执行语句的时候,是按照以下顺序执行的:

where->group by->having->select->order by

因为别名是在select里面取的,要在select之后才能被识别,所以where,group by, having都不可以用别名,order by可以用别名。
解决方法:
  1. 在where,group by, having用原字段构成的表达式
  2. 在在内层加个子查询,把字段名字改了,再在外层用where,group by, having

Q10:hive怎么确定mapper、reducer的个数?

  1. 对于mapper:根据传入文件的个数及大小,一个文件对应一个mapper,若文件超出128M,则拆分到两个mapper
  2. 对于reducer:根据输入的数据量,及以下两个参数,hive自动估计

hive.exec.reducers.bytes.per.reducer(每个reducer最多可接受数据量,默认为1000^3)
hive.exec.reducers.max(集群中最多可以开多少个reducer,默认为999)

但是mapper不宜过多,每个mapper都需要启动的开销,一个mapper启动和初始化的时间远远大于逻辑处理的时间,就会造成很大的资源浪费。

Q11:分区、分桶、索引的区别?

  1. 分区:hive通常会对全表扫描,如果使用了分区,就避免全表扫描,提高查询效率。Hive的分区使用HDFS的子目录功能实现,把一个大表的数据按照某个字段划分,分别放到不同的文件夹里,文件夹名字就是“字段+字段值”。但是这个字段其实是伪字段,它并不存在于表的数据里。
  2. 分桶:在分区数量过于庞大以至于可能导致文件系统崩溃时,我们就需要使用分桶来解决问题了。分桶将整个表或者某个分区内所有数据,按照某字段的hash值取模进行区分。分桶可以指定桶的个数,不像分区不确定分区的个数(可能会出现很多个分区)。如果join的两个表对key字段都做了分桶,那么是很有利于mapjoin的。分桶是依据数据表中真实的字段而不是伪字段。
  3. 索引:在hive中比较少用,适用于不更新的静态字段,以免总是重建索引数据。每次建立、更新数据后,都要重建索引以构建索引表。使用索引查询时,首先需要一个mp job来扫描索引表,然后才能去扫描表数据,非常繁琐。

你可能感兴趣的:(大数据)