文章目录
- Hive
- 1.*描述一下Hive动态分区和分桶使用场景和使用方法?
- Hive是怎么集成HBase的?具体讲讲?
- 3.Hive查询的时候on和where有什么区别?为什么?
- 4.Hive里面的left join是怎么回事?它是怎么执行的?
- 5.*说一下Hive内部表,外部表,分区表?
- 6.*Hive和mysql有什么区别,大数据为什么不用MySQL做存储和数据处理?
- 7.*Hive如何调优?
- 8.*Hive数据倾斜原因和处理?
- 9.Hive的自定义函数实现了什么接口什么方法?
- 10.使用Hive-sql如何查询A表中B表不存在的数据?
- 11.*如何控制Hive中Mapper和Reduce的个数?
- 12.*请说明Hive中Sort By,Order By, Cluster By,Distrbute By的作用?
- 14.简要描述数据库中的null,说出null在Hive底层如何存储,并解释select a.* from t1 a left outer join t2 b on a.id=b.id where b.id is null的含义?
- 15.*Hive有哪些保存元数据的方式,每个有什么特点。
- 16.生产环境中为什么建议使用外部表?
Hive
1.*描述一下Hive动态分区和分桶使用场景和使用方法?
1.分区
按照数据表的某列或某些列分为多个分区,分区从形式上可以理解为文件夹,比如我们要收集某个大型网站的日志数据,一个网站每天的日志数据存在同一张表上,由于每天会生成大量的日志,导致数据表的内容巨大,在查询时进行全表扫描耗费的资源非常多。那其实这个情况下,我们可以按照日期对数据进行分区,不同日期的数据存放在不同的分区,在查询时只要指定分区字段的值就可以直接从该分区查找。分区是以字段的形式在表结构中存在,通过describe table命令可以查看字段存在,但是该字段不存放实际的数据内容,仅仅是分区的表示(伪列)。
- 静态分区
create table if not exists sopdm.wyp2(id int,name string,tel string)
partitioned by(age int) row format delimited fields terminated by ‘,’ stored as textfile;
–overwrite是覆盖,into是追加
insert into table sopdm.wyp2 partition(age=‘25’) select id,name.tel from sopdm.wyp; - 动态分区
–设置为true表示开启动态分区功能(默认为false)
set hive.exec.dynamic.partition=true;
–设置为nonstrict,表示允许所有分区都是动态的(默认为strict)
set hive.exec.dynamic.partition.mode=nonstrict;
–insert overwrite是覆盖,insert into是追加
set hive.exec.dynamic.partition.mode=nonstrict;
insert overwrite table sopdm.wyp2 partition(age) select id,name.tel,age from sopdm.wyp; - 静态分区和动态分区的区别
静态分区与动态分区的主要区别在于静态分区是手动指定,而动态分区是通过数据来进行判断。详细来说:
静态分区:
- 静态分区是在编译期间指定的指定分区名。
- 支持load和insert两种插入方式。
- 适用于分区数少,分区名可以明确的数据。
动态分区: - 根据分区字段的实际值,动态进行分区。
- 是在sql执行的时候进行分区。
- 需要先将动态分区设置打开。
set hive.exec.dynamic.partition.mode=nonstrict - 只能用insert方式。
- 通过普通表选出的字段包含分区字段,分区字段放置在最后,多个分区字段按照分区顺序放置。
2.分桶
分桶是相对分区进行更细粒度的划分。分桶将整个数据内容安装某列属性值得hash值进行区分,如果安装name属性分为3个桶,就是对name属性值的hash值对3取模,按照取模结果对数据分桶。汝取模结果为0的数据记录存放到一个文件,取模为1的数据存放到一个文件,取模为2的数据存放到一个文件。
CREATE TABLE bucketed_user(id INT) name STRING CLUSTERED BY (id) INTO 4 BUCKETS;
对于每一个表(table)或者分区,可以进一步组织成桶,也就是说桶是更为细粒度的数据范围划分。Hive也是针对某一列进行桶的组织。Hive采用对列值哈希,然后除以桶的个数求余的方式决定该条记录存放在哪个桶当中。把表(或者分区)组织成桶(Bucket)有两个理由:
- 获得更高的查询处理效率
桶为表加上了额外的结构,Hive在处理有些查询时能利用这个结构。具体而言,连接两个在(包含连接列的)相同列上划分了桶的表,可以使用Map端连接(Map-side join)高效的实现。比如JOIN操作。对于JOIN操作两个表有一个相同的列,如果对这两个表都进行了桶操作。那么将保存相同列值的桶进行JOIN操作就可以,可以大大减少JOIN的数据量。 - 使取样(sampling)更高效
在处理大规模数据集时,在开发和修改查询的阶段,如果能在数据集的一小部分数据上试运行查询,会带来很多方便。
技巧
一般问到Hive分区,基本上都会问动态分区和静态分区的区别。所以要能够答出他们之间的区别。同时要清晰用法和应用场景。
另外,需要能够结合项目说,自己在项目中,哪些地方用了动态分区。一般涉及按日期分区的,比较多是动态分区。
注意
对于分桶表,工作中实际应用场景不多,但需要了解其原理(分桶不要求重点掌握)。
Hive是怎么集成HBase的?具体讲讲?
- 首先我们需要将HBase的客户端jar拷入Hive lib目录下。
- 修改hive/conf下的hive-site.xml配置文件,在最后添加如下属性。
hbase.zookeeper.quorum
hadoop
- 启动Hive,创建表管理表hbase_table_1,指定数据存储在HBase表中。
类似下面的方式:
stored by ‘org.apache.hadoop.hive.hbase.HBaseStorageHandler’
with serdeproperties
(“hbase.columns.mapping”=":key,accuracy:total_score,accuracy:question_count,accuracy:accuracy")
tblproperties(“hbase.table.name”=“exam:analysis”); - 往Hive表hbase_table_1表中插入数据。
注意
CDH版本不需要额外操作,相同CDH版本下的软件,已经做过整合。
技巧
如果使用CDH版本,回答重点放在集成的代码上。相关的代码格式需要掌握,需要能够答出Stored by的类型,HBaseStorageHandler的类。
如果使用的Apache版本,还需要能够答出大致的整合步骤。
3.Hive查询的时候on和where有什么区别?为什么?
左右关联时:
- 条件不为主表条件时,放在on和where后面一样。
- 条件为主表条件时,放在on后面,结果为主表全量,放在where后面为主表条件筛选过后的全量。
- select * from a left join b on a.id=b.id and a.dt=20181115;
- select * from a left join b on a.id=b.id and b.dt=20181115;
- select * from a join b on a.id=b.id and a.dt=20181115;
- sellect * from a left join b on a.id=b.id where a.dt=20181115;
sql1: 如果是left join 在on 上写主表a的条件不会生效,全表扫描。
sql2: 如果是left join 在 on 上写副表b的条件会生效,但是语义与写到where条件不同。
sql3: 如果是inner join 在on 上写主表a,副表b的条件都会生效。
sql4: 建议这么写,大家写sql 大部分的语义都是先过滤数据然后再join,所以在不了解 join on +条件的情况下,条件尽量别写到on后,直接写到where后就ok了。
技巧
能够讲出join时,on和where的区别,可以通过举例子的方式进行讲解。on中的条件是在join时执行,where中的条件,是在join结束后对结果进行执行。
4.Hive里面的left join是怎么回事?它是怎么执行的?
不考虑where条件下,left join会把左表所有数据查询出来,on及其后面的条件仅仅会影响右表的数据(符合就显示,不符合全部为null)。
在join阶段。where字句的条件都不会被使用,仅在join阶段完成以后,where子句条件才会被使用,它将从匹配阶段产生的数据中检索过滤。
所以左连接关注的是左边的主表数据,不应该把on后面的从表中的条件加到where后,这样会影响原有主表的数据。
where后面:是先连接生成临时查询结果,然后再筛选on后面:先根据条件过滤筛选,再连接生成临时查询结果。
对于条件在on加个and还是用子查询。查询结果是一模一样的,至于如何使用这个需要分情况,用子查询的话会多一个maptask,但是如果利用这个子查询能过滤很多数据的话,用子查询还是比较建议的,因为不会加载太多的数据到内存中,如果过滤数据不多的情况下,建议用on后面加and条件。
技巧
需要能够讲出left join的用法以及特点即可。该问题比较基础。
5.*说一下Hive内部表,外部表,分区表?
1.内部表
- 与数据库中的Table在概念上是类似的。
- 没一个Table在Hive中都有一个相应的目录存储数据。
- 所有的Table数据(不包括 External Table)都保存在这个目录中。
- 删除表时,元数据与数据都会被删除。
2.外部表
- 指向已经在HDFS中存在的数据,可以创建Partition。
- 它和内部表在元数据的组织上是相同的,而实际数据的存储则有较大的差异。
- 外部表只有一个过程,加载数据和创建表同时完成,并不会移动到数据库目录中,只是与外部数据建立一个连接,当删除一个外部表时,仅删除连接和元数据。
3.分区表
- Partition 对应于数据库的Partition列的密集索引。
- 在Hive中,表中的一个Partition对应于表下的一个目录,所有的Partition的数据都存储在对应的目录中。
技巧
问题比较基础,需要能够答出他们之间的区别,以及相对应的应用场景,以及语法(笔试或者现场写代码)。
6.*Hive和mysql有什么区别,大数据为什么不用MySQL做存储和数据处理?
Hive是基于Hadoop构建的一套数据仓库分析系统,它提供了丰富的SQL查询方式来分析存储在Hadoop分布式文件系统中的数据;可以将结构化的数据文件映射为一张数据库表,并提供完整的SQL查询查询功能;可以将SQL语句转换为MapReduce任务运行,通过自己的SQL查询分析需要的内容,这套SQL简称Hive SQL,使不熟悉MapReduce的用户可以很方便地利用SQL语言查询,汇总和分析数据。而MapReduce开发人员可以把自己写的mapper和reduce作为插件来支持Hive做更复杂的数据分析。
它与关系型数据库的SQL略有不同,但支持了绝大多数的语句如DDL,DML以及常见的聚合函数,连接查询,条件查询。它还提供了一系列的工具进行数据提取转化加载,用来存储,查询和分析存储在Hadoop中的大规模数据集。并支持UDF(User-Defined Function),UDAF(User-Defnes AggregateFunction)和UDTF(User-Defined Table-Generating Function),也可以实现对map和reduce函数的定制,为数据操作提供了良好的伸缩性和可扩展性。
Hive不适合用于联机(online)事务处理,也不提供实时查询功能。它最适合应用在基于大量不可变数据的批处理作业。Hive的特点包括:可伸缩(在Hadoop的集群上动态添加设备),可扩展。容错,输入格式的松散耦合。
Hive构建在基于静态批处理的Hadoop之上,Hadoop通常都有较高的延迟并且在作业提交和调度的时候需要大量的开销。因此,Hive并不能够在大规模数据集上实现低延迟快速的查询,例如,Hive在几百MB的数据集上执行查询一般有几分钟级的时间延迟。
因此,Hive并不适合那些需要高实性的应用,例如,联机事务处理(OLTP)。Hive查询操作过程严格遵守Hadoop MapReduce的作业执行模型,Hive将用户的HiveQL语句通过解释器转换为MapReduce作业提交到Hadoop集群上,Hadoop监控作业执行过程,然后返回作业执行结果给用户。Hive并非为联机事务处理而设计,Hive并不提供实时的查询和基于行级的数据更新操作。Hive的最佳使用场合是大数据集的批处理作业,例如,网络日志分析。
总结如下:
- 查询语言不同:Hive是hql语言,mysql是sql语句;
- 数据存储位置不同:Hive是把数据存储在HDFS上,而mysql数据是存储在自己的系统中;
- 数据格式:Hive数据格式可以用户自定义,mysql有自己的系统定义格式;
- 延迟性:Hive延迟性高,而mysql延迟性低
- 数据规模:Hive存储的数据量超级大,而mysql只是存储一些少量的业务数据;
- 底层执行原理:Hive底层是用的MapReduce,为mysql是excutor执行器。
技巧
能够讲出Hive和mysql的几点不同,以及相对应的原因。比如讲Hive查询慢,需要讲出Hive为什么慢,讲Hive支持大数据,需要讲出为什么支持大数据。
7.*Hive如何调优?
- 设置本地模式。
- 并行执行。
- JVM重用。
- 严格模式。
- 合理设置map和reduce的数量。
- Fetch抓取。
- 防止数据倾斜参数的开启,会生成两个MR Job。
- explain执行计划,通过执行计划来调节SQL语句。
技巧
该处是面试重点,一般需要能够答出几种调优手段。参考课件内容,需要能够讲出具体怎么调优。比如合理设置Map和Reduce数,需要能够讲出具体怎么设置。
8.*Hive数据倾斜原因和处理?
1.产生原因
- key分布不均匀。
- 业务数据本身的特性。
- 建表时考虑不周。
- 某些SQL语句本身就有数据倾斜,例如:
- 大表join小表,其中小表key集中,分发到某一个或几个Reduce上的数据远高平均值。
- 大表join小表,但是分桶的判断字段0值或空值过多,这些空值都由一个reduce处理,非常慢。
- group by,group by维度过小,某值的数量过多,处理某值的reduce非常耗时
- Count Distinct,某特殊值过多,处理此特殊值的reduce耗时。
2.解决方案
[参数调节]
hive.map.aggr=true
Map端部分聚合,相当于Combinerhive.groupby.skewindata=true
有数据倾斜的时候进行负载均衡,当选项设定为true,生成的查询计划会有两个MRJob。第一个MRJob中,Map的输出结果集合会随机分布到Reduce中,每个Reduce做部分聚合操作,并输出结果,这样处理的结果是相同的Group By Key有可能被分发到不同的Reduce中,从而达到负载均衡的目的;第二个MR Job再根据预处理的数据结果按照Group By Key分布到Reduce中(这个过程可以保证相同的Group By Key被分布到同一个Reduce中),最后完成最终的聚合操作。
[SQL调整]
- 如何Join:关于驱动表的选取,选用join key分布最均匀的表作为驱动表,做好列裁剪和filter操作,以达到两表做join的时候,数据量相对变小的效果。
- 大小表Join:使用map join让小的维度表(1000条以下的记录条数)先进内存。在map端完成reduce。
- 大表Join大表:把空值的key变成一个字符串加上随机数,把倾斜的数据分到不同的reduce上,由于null值关联不上,处理后并不影响最终结果。
- count distinct大量相同特殊值,将值为空的情况单独处理,如果是计算count distinct,可以不用处理,直接过滤,在最后结果中1。如果还有其他计算,需要进行group by,可以先将值为空的记录单独处理,再和其他计算结果进行union。
- group by维度过小:采用sum() group by的方式来替换count(distinct)完成计算。
- 特殊情况特殊处理:在业务逻辑优化效果的不大情况下,有些时候是可以将倾斜的数据单独拿出来处理。最后union回去。
技巧
该问题比较常用,大部分都会问到,所以需要重点掌握。需要能够说出产生数据倾斜的几种情况,然后相对应的如何解决。另外,还需要结合自己项目进行去讲:在哪个业务场景下,因为什么原因产生了数据倾斜,最后是如何解决的。需要在理解SQL优化的基础上,讲一下自己用了哪些SQL优化。
9.Hive的自定义函数实现了什么接口什么方法?
Hive自定义函数包括三种 UDF,UDAF,UDTF:
- UDF(User-Defined-Function)一进一出,继承了org.apache.hadoop.hive.ql.exec.UDF类,并覆写了evaluate方法。
- UDAF(User-Defined Aggregation Funcation) 聚合函数,多进一出。如 Count/max/min
- UDTF(User-Defined Table-Generating Functions)一进多出,如lateral view explore
技巧
自定义函数的分类是基础问题,一般深入问的话,会问你写过什么自定义函数?实现什么功能?其中实现了哪些接口和方法?
10.使用Hive-sql如何查询A表中B表不存在的数据?
- select distinct A.ID from A where A.ID not in(select ID from B)
- select * from A where(select count(1)as num from A where A.ID=B.ID)=0
技巧
考察SQL能力,这里只是示例,需要平时加强对SQL的练习。
11.*如何控制Hive中Mapper和Reduce的个数?
1.控制Hive任务中的map数
通常情况下,作业会通过input的目录产生一个或者多个map任务。
主要的决定因素有:input的文件总个数,input的文件大小,集群设置的文件块大小(目前为128M,可在Hive中通过set dfs.block.size;命令查看到,该参数不能自定义修改)
举例:假设input目录下有1个文件a,大小为780M,那么Hadoop会将该文件a分隔成7个块(6个128m的块和一个12m的块),从而产生7个map数假设input目录下有3个文件a,b,c,大小分别为10m,20m,130m,那么Hadoop会分隔成4个块(10M,20M,128M,2M),从而产生4个map数,即,如果文件大于块大小(128M),那么会拆分,如果小于块大小,则把该文件当成一个块。
问题1:是不是map数越多越好?
答案是否定的。如果一个任务有很多小文件(远远小于块大小128M),则每个文件也会被当做一个块,用一个map任务来完成,而一个map任务启动和初始化的时间远远大于逻辑处理的时间,就会造成很大的资源浪费。而且,同时可执行的map数是受限的。
问题2:是不是保证每个map处理接近128M的文件块,就高枕无忧了?
答案也是不一定。比如有一个127M的文件,正常会用一个map去完成,但这个文件只有一个或者两个小字段,却有几千万的记录,如果map处理的逻辑比较复杂,用一个map任务去做,肯定也比较耗时。
针对上面的两个问题,我们需要采用两种方式来解决:即减少map数和增加map数。
- 如何合并小文件,减少map数?
假设一个SQL任务:
select count(1) from popt_tbaccountcopy_mes where pt=‘2012-07-04’;
该任务的 inputdir /group/p_sdo_data/p_sdo_data_etl/pt/popt_tbaccountcopy_mes/pt=2012-07-04共有194个文件,其中很多是远远小于128M的小文件,总大小9G,正常执行会用194个map任务。Map总共消耗的计算资源:SLOTS_MILLIS_MAPS=623,020我通过以下方法来在map执行前合并小文件,减少map数:
set mapred.max.split.size=100000000;
set mapred.min.split.size.per.node=100000000;
set mapred.min.split.size.per.rack=100000000;
set hive.input.format=org.apache.hadoop.hive.ql.io.CombineHiveInputFormat;
再执行上面的语句,用了74个map任务,map消耗的计算资源:SLOTS_MILLIS_MAPS=333,500,对于这个简单SQL任务,执行时间上可能差不多,但节省了一半的计算资源。大概解释一下,100000000表示100M,set hive.input.format=org.apache.hadoop.hive.ql.io.CombineHiveInputFormat;这个参数表示执行前进行小文件合并,前面三个参数确定合并文件块的大小,大于文件块大小128M的,按照128M来分隔,小于128M,大于100M的。按照100M来分隔,把那些小于100M的(包括小文件和分隔大文件剩下的),进行合并,最终生成了74个块。 - 如何适当的增加map数?
当input的文件都很大,任务逻辑复杂,map执行非常慢的时候,可以考虑增加Map数,来使得每个map处理的数据量减少,从而提高任务的执行效率。假设有这样一个任务:
select data_desc,
count(1),
count(distinct id),
sum(case when …),
sum(case when …),
sum(…)
from a group by data_desc
如果表a只有一个文件,大小为120M,但包含几千万的记录,如果用一个map去完成这个任务,肯定是比较耗时的,这种情况下,我们要考虑将这一个文件合理的拆分成多个,这样就可以用多个map任务去完成。
set mapred.reduce.task=10;
create table a_1 as
select * from a
distribute by rand(123);
这样会将a表的记录,随机的分散到包含10个文件的a_1表中,再用a_1代替上面sql中的a表,则会用10个map任务去完成。每个map任务处理大于12M(几百万记录)的数据,效率肯定会好很多。
看上去,貌似这两种有些矛盾,一个是要合并小文件,一个是要把大文件拆成小文件,这点正是重点需要关注的地方,根据实际情况,控制map数量需要遵循两个原则:使大数据量利用合适的map数;使单个map任务处理合适的数据量。
2.控制Hive任务的reduce数
Hive自己如何确定reduce数;reduce个数的设定极大影响任务执行效率,不指定reduce个数的情况下,Hive会猜测确定一个reduce个数,基于以下两个设定:
hive.exec.reducers.bytes.per.reducer(每个reduce任务处理的数据量,默认为1000^3=1G)
hive.exec.reducers.max(每个任务最大的reduce数,默认为999)
计算reduce数的公式很简单N=min(参数2,总输入数据量/参数1)。即,如果reduce的输入(map的输出)总大小不超过1G,那么只会有一个reduce任务;如:
select pt,count(1) from popt_tbaccountcopy_mes where pt='2012-07-04’group by pt;
/group/p_sdo_data/p_sdo_data_etl/pt/popt_tbaccountcopy_mes/pt=2012-07-04 总大小为9G多,因此这句话有10个reduce
- 调整reduce个数方法一:
调整hive.exec.reducers.bytes.per.reducer参数的值;
set hive.exec.reduce.bytes.per.reducer=500000000;(500M)
select pt,count(1) from popt_tbaccountcopy_mes where pt=‘2012-07-04’ group by pt;
这次有20个reduce - 调整reduce个数方法二:
set mapred.reduce.tasks=15;
select pt,count(1) from popt_tbaccountcopy_mes where pt=‘2012-07-04’ group by pt;
这次有15个reduce
reduce个数并不是越多越好。
同map一样,启动和初始化reduce也会消耗时间和资源;另外,有多少个reduce,就会有多少个输出文件,如果生成了很多个小文件,那么如果这些小文件作为下一个任务的输入,则也会出现小文件过多的问题;
什么情况下只有一个reduce?
很多时候你会发现任务中不管数据量多大,不管你有没有设置调整reduce个数的参数,任务中一直都只有一个reduce任务;其实只有一个reduce任务的情况,除了数据量小于hive.exec.reducers.bytes.per.reducer参数值的情况外,还有以下原因:
- 没有group by的汇总。
比如把select pt,count(1) from popt_tbaccountcopy_mes where pt=‘2012-07-04’ group by pt;写成select pt,count(1) from popt_tbaccountcopy_mes where pt=‘2012-07-04’;这点非常常见,希望大家尽量改写。 - Order by。
- 有笛卡尔积。
通常这些情况下,除了找办法来变通和避免,暂时没有什么好的办法,因为这些操作都是全局的,所以Hadoop不得不用一个reduce去完成;同样的,再设置reduce个数的时候也需要考虑这两个原则:使大数据量利用合适的reduce数;使单个reduce任务处理合适的数据量。
技巧
此类问题属于比较深一些的问题,但是很多面试中都会问。需要能够答出mapper和Reducer是通过什么决定的,如果调优时,如何控制。高分面试必备,需要能够理解文档中内容,理解记忆。
12.*请说明Hive中Sort By,Order By, Cluster By,Distrbute By的作用?
1.order by
Hive中的order by跟传统的sql语言中的order by作用是一样的,会对查询的结果做一次全局排序,所以说,只有Hive的sql中制定了order by所有的数据都会到同一个reduce进行处理(不管有多少map,也不管文件有多少的block只会启动一reduce)。但是对于大量数据这将会消耗很长的时间去执行。这里跟传统的sql还有一点区别:如果指定了hive.mapred.mode=strict(默认值是nonstrict),这时就必须指定limit来限制输出条数,原因是:所有的数据都会在同一个reduce端进行,数据量大的情况下可能不能出结果,那么在这样的严格模式下,必须指定输出的条数。
2.sort by
Hive中指定了sort by,那么在每个reducer端都会做排序,也就是说保证了局部有序(每个reducer出来的数据是有序的,但是不能保证所有的数据是有序的,除非只有一个reducer),好处是:执行了局部排序之后可以为接下来的全局排序提高不少的效率(其实就是做一次归并排序就可以做到全局排序了)。
3.distribute by 和 sort by 一起使用
distribute by是控制map的输出在reduce是如何划分的,举个例子,我们有一张表,mid是指这个store所属的商户,money是这个商户的盈利,name是这个store的名字,执行Hive语句:select mid,money,name from store distribute by mid sort by mid asc,money asc。我们所有的mid相同的数据会被送到同一个reducer去处理,这就是因为指定了distribute by mid,这样的话就可以统计出每个商户中各个商店盈利的排序了(这个肯定是全局有序的,因为相同的商户会放到同一个reducer去处理)。这里需要注意的是distribute by必须要写在sort by之前。
4.cluster by
cluster by的功能就是distribute by 和sort by相结合,如下2个语句是等价的:
select mid,money,name from store cluster by mid
select mid,money,name from store distribute by mid sort by mid
如果需要获得与3中语句一样得效果:
select mid,money,name from store cluster by mid sort by money
注意
被cluster by指定得列只能是降序,不能指定asc和desc。
技巧
问题偏基础。需要能够答出四种排序用法的应用场景和区别。
13,请说明Hive中split,coalesce以及collect list函数的用法?
- split将字符串转化为数组,即:split(‘a,b,c,d’,’,’) ==>[“a”,“b”,“c”,“d”]。
- coalesce(T v1,T v2,…)返回参数中的第一个非空值;如果所有值都为NULL,那么返回NULL。假如某个字段默认是null,你想其返回的不是null,而是比如0或其他值,可以使用这个函数
select coalesce(field_name,0) as value from table; - collect_list将分组中的某列转化为一个数据返回,不去重(列转行函数)。
select collect_list(id) from table; - collect_set也是将分组中的某列转化为一个数组返回,但是去重。
技巧
考察Hive中的函数的使用方法。难度不大。需要增加对SQL的练习。另外还有窗口函数,需要加强练习。
14.简要描述数据库中的null,说出null在Hive底层如何存储,并解释select a.* from t1 a left outer join t2 b on a.id=b.id where b.id is null的含义?
- null与任何值运算的结果都是null,可以使用is null,is not null函数指定其值为null情况下的取值。
- null 在hive底层默认是用‘\N’来存储的,可以通过alter table test SET SERDEPROPERTIES(‘serialization.null.format’=‘a’);来修改。
- 查询出t1表中存在但是t2表中不存在的id相对应的t1表的所有字段。
技巧
基础问题。考察null在Hive中的使用。需要能够讲出null运算结果,查询方式,以及底层存储。
15.*Hive有哪些保存元数据的方式,每个有什么特点。
- 内嵌模式。内嵌数据库derby,安装小,基于Java,JDBC和SQL标准。
- 本地模式。MySql数据库,数据存储模式可以自己设置,持久化好,查看方便。
- 远程模式。用于非Java客户端访问元数据库,在服务器端启动MetaStoreServer,客户端利用Thrift协议通过MetaStoreServer访问元数据库。它将Metastore分离出来,成为一个独立的Hive服务(Merastore服务还可以部署多个)。这样的模式可以将数据库层完全置于防火墙后,客户端就不再需要用户名和密码登录数据库,避免了认证信息的泄露。
技巧
基础问题。考察Hive元数据的保存方式,主要有三种。一般我么使用的是本地模式。另外需要了解远程模式。需要能够答出远程模式使用的是Thrift协议。
16.生产环境中为什么建议使用外部表?
- 因为外部表不会加载数据到Hive,减少数据传输,数据还能共享。
- Hive不会修改数据,所以无需担心数据的损坏。
- 删除表时,只删除表结构,不删除数据。
技巧
考查外部表的特点。基础问题。