文章目录

  • 一,Hive是什么,和DBMS有什么异同?
  • 二,sort by、order by、partition by、cluster by有什么区别
  • 三,解释`select a.* from t1 a left outer join t2 b on a.id=b.id where b.id is null;`
  • 四,写出hive中split、coalesce及collect_list函数的用法(可举例)?
  • 五,Hive有哪些方式保存元数据,各有哪些特点?
  • 六,Hive内部表和外部表的区别?
  • 七,HiveSQL转换为MapReduce的过程
  • 十,请把下面语句用Hive实现
  • 十一,写出将 text.txt 文件放入 hive 中 test 表‘2016-10-10’ 分区的SQL语句(test 的分区字段是 l_date)
  • 十二,Hive的权限控制
  • 十三,Hive的存储和压缩
  • 存储格式:
  • 压缩格式:
  • 十四,Hive join过程中大表小表的放置顺序?
  • 十五,Hive中使用什么代替in查询?
  • 十六,Hive的函数:UDF、UDAF、UDTF的区别?
  • 十七,对Hive桶表的理解?
  • 十八,Hive优化
  • 1,Fetch抓取
  • 2,本地模式


一,Hive是什么,和DBMS有什么异同?

Hive是基于MapReduce和HDFS的数据仓库工具,Hive不是数据库,不具备存储能力和计算能力,其计算能力基于MapReduce,其存储能力依赖于HDFS。

Hive和DBMS相似的是提供了SQL接口,Hive结合其元数据管理和SQL引擎将SQL翻译为MapReduce任务。

二,sort by、order by、partition by、cluster by有什么区别

  • order by 是全局排序,reduce只能有一个,否则无法保证全局顺序
  • sort by是任务内有序
  • partition by相当于spark的group by,按照指定的字段执行shuffle,将相同的key分发到同一个reduce
  • cluster by相当于partition by + sort by,即分区又按照分区字段排序

三,解释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');来修改。
  • 注意题中是left outer join,如果是join会查不出数据

四,写出hive中split、coalesce及collect_list函数的用法(可举例)?

  • split将字符串转化为数组,即:split(‘a,b,c,d’ , ‘,’) ==> [“a”,“b”,“c”,“d”]
  • coalesce(T v1, T v2, …) 返回参数中的第一个非空值;如果所有值都为 NULL,那么返回NULL
  • collect_list列出该字段所有的值,不去重 select collect_list(id) from table

五,Hive有哪些方式保存元数据,各有哪些特点?

  • 1)Single User Mode:默认安装hive,hive是使用derby内存数据库保存hive的元数据,这样是不可以并发调用hive的。
  • 2)Local Mode:hive服务和metastore服务运行在同一个进程中,使用本机mysql服务器存储元数据。mysql可以远程部署,也可以本地部署。
  • 3)Remote Server Mode:hive服务和元数据服务不在一个进程,元数据服务单独部署。

所谓Local与Remote指的是hive服务是否和元数据服务在同一个进程,和mysql的部署无关。

六,Hive内部表和外部表的区别?

Hive内部表和外部表最主要的区别在于数据文件是否由Hive管理,内部表数据所在文件由Hive管理,在删除表时连同文件一起删除;外部表数据所在文件不由Hive管理,在删除表时不会删除文件。

Hive默认创建内部表,创建外部表需要加上external关键字。

七,HiveSQL转换为MapReduce的过程

Created with Raphaël 2.3.0 开始 HiveSql AST(抽象语法树) QB(查询块) OperatorTree(操作树) MapReduce(任务树) 结束


① HiveSQL经过词法、语法、语义解析后生成抽象语法树,SQL的每个关键字对应抽象语法树的一个结点Node

②将抽象语法树进一步抽象和封装,形成QueryBlock,QueryBlock可以理解为查询的基本单元,包括输入、计算、输出,一个复杂的SQL必然可以转换为多个基本的BlockQuery

③遍历BlockQuery,将BlockQuery转换为OperatorTree,构成Operator树

④OperatorTree转换为MapReduce,完成之后,就构成了MapReduce树,这就是所谓的物理执行计划。之后Hadoop根据MapReduce树调度执行任务。

十,请把下面语句用Hive实现

SELECT a.key,a.value 
FROM a 
WHERE a.key not in (SELECT b.key FROM b)

考点:HiveSQL不支持 in 和 not in(0.31前的版本不支持,之后的版本都支持,这是一个过时的面试题),not in 可以用not exists替代

答案:

select a.key,a.value from a where a.key not exists (select b.key from b)

思考下,如果是in,该如何替换?

SELECT a.key,a.value 
FROM a 
WHERE a.key in (SELECT b.key FROM b)

答案:

select a.key,a.value from a  left semi join  b on a.key = b.key

十一,写出将 text.txt 文件放入 hive 中 test 表‘2016-10-10’ 分区的SQL语句(test 的分区字段是 l_date)

load data local inpath 'text.txt' 
overwrite into table test partition(i_date='2016-10-10')

如果是本地文件系统要加关键字local,如果是HDFS文件系统,不需要关键字local

十二,Hive的权限控制

参考文章参考文章参考文章

有两种权限控制方式:

  • 基于元数据的权限控制。直接通过HDFS或Hive Client访问Hive的数据(如hive command line,pig,spark,hue),需要对Hive在HDFS中的数据进行相关的权限控制,通过HDFS权限控制,进而可以控制Hive SQL相关的操作权限。可以使用Storage Based Authorization的授权方式。
  • 基于HiveServer2的权限控制。不能直接通过HDFS或Hive Client访问,只能通过HiveServer2(如Beeline或JDBC) 等来执行Hive相关的命令,可以使用SQL Standards Based Authorization的授权方式

十三,Hive的存储和压缩

参考文章

存储格式:

  • TEXTFILE
create table if not exists textfile_table(
    site string,
    url  string,
    pv   bigint,
    label string)
row format delimited fields terminated by '\t'
stored as textfile;

-- 插入数据操作:

set hive.exec.compress.output=true;  
set mapred.output.compress=true;  
set mapred.output.compression.codec=org.apache.hadoop.io.compress.GzipCodec;  
set io.compression.codecs=org.apache.hadoop.io.compress.GzipCodec;  
insert overwrite table textfile_table select * from textfile_table;
  • ORC
CREATE TABLE IF NOT EXISTS itcast_dws.visit_dws (
  sid_total INT COMMENT '根据sid去重求count',
  sessionid_total INT COMMENT '根据sessionid去重求count',
  ip_total INT COMMENT '根据IP去重求count',
  area STRING COMMENT '区域信息',
  seo_source STRING COMMENT '搜索来源',
  origin_channel STRING COMMENT '来源渠道',
  hourinfo STRING COMMENT '创建时间,统计至小时',
  quarterinfo STRING COMMENT '季度',
  time_str STRING COMMENT '时间明细',
  from_url STRING comment '会话来源页面',
  groupType STRING COMMENT '产品属性类型:1.地区;2.搜索来源;3.来源渠道;4.会话来源页面;5.总访问量',
  time_type STRING COMMENT '时间聚合类型:1、按小时聚合;2、按天聚合;3、按月聚合;4、按季度聚合;5、按年聚合;')
comment 'EMS访客日志dws表'
PARTITIONED BY(yearinfo STRING,monthinfo STRING,dayinfo STRING)
ROW FORMAT DELIMITED
FIELDS TERMINATED BY '\t'
stored as orc
location '/user/hive/warehouse/itcast_dws.db/visit_dws'
TBLPROPERTIES ('orc.compress'='SNAPPY');
create table if not exists rcfile_table(
    site string,
    url  string,
    pv   bigint,
    label string)
row format delimited fields terminated by '\t'
stored as orc;
  • RC
create table if not exists rcfile_table(
    site string,
    url  string,
    pv   bigint,
    label string)
row format delimited fields terminated by '\t'
stored as rcfile;
  • SEQUENCEFILE
create table if not exists seqfile_table(
    site string,
    url  string,
    pv   bigint,
    label string)
row format delimited fields terminated by '\t'
stored as sequencefile;
插入数据操作:

set hive.exec.compress.output=true;  
set mapred.output.compress=true;  
set mapred.output.compression.codec=org.apache.hadoop.io.compress.GzipCodec;  
set io.compression.codecs=org.apache.hadoop.io.compress.GzipCodec;  
set mapred.output.compression.type=BLOCK;
insert overwrite table seqfile_table select * from textfile_table;
  • Parquet

存储格式

存储方式

特点

TextFile

行存储

存储空间消耗比较大,可以使用gz压缩,但压缩的text,无法分割和合并;因为要逐个字符判断是否是分隔符,所以查询的效率最低;可以在只写不读的场景下结合gz压缩;或者不压身,可以直接存储,读效率高

SequenceFile

行存储

存储空间消耗最大,压缩的文件可以分割和合并,查询效率高,需要通过text文件转化来加载

RCFile

数据按行分块,每块按照列存储

存储空间最小,查询的效率最高 ,需要通过text文件转化来加载,加载的速度最低。压缩快,快速列存取。读记录尽量涉及到的block最少 读取需要的列只需要读取每个row group 的头部定义。 读取全量数据的操作,性能比sequencefile没有明显的优势

ORCFile

数据按行分块 每块按照列存储

压缩快,快速列存取 ,效率比rcfile高,是rcfile的改良版本

Parquet

列存储

相对于PRC,Parquet压缩比较低,查询效率较低,不支持update、insert和ACID.但是Parquet支持Impala查询引擎

压缩格式:

确定了存储格式之后,再考虑使用什么压缩算法,因为不同算法支持存储格式不一样

Hive支持的压缩方式:

  • 不压缩
  • Snappy
  • Gzip
  • ZLIB
  • LZO

Hive支持的压缩算法:

hive理论知识 hive基础知识测试题_字段

hive理论知识 hive基础知识测试题_Hive_02

十四,Hive join过程中大表小表的放置顺序?

将最大的表放置在JOIN语句的最右边,或者直接使用/*+ streamtable(table_name) */指出。

在编写带有 join 操作的代码语句时,应该将条目少的表/子查询放在 Join 操作符的左边。

因为在 Reduce 阶段,位于 Join 操作符左边的表的内容会被加载进内存,载入条目较少的表可以有效减少 OOM(out of memory)即内存溢出。

所以对于同一个 key 来说,对应的 value 值小的放前,大的放后,这便是“小表放前”原则。

若一条语句中有多个 Join,依据 Join 的条件相同与否,有不同的处理方法。

十五,Hive中使用什么代替in查询?

在Hive 0.13版本之前,通过left outer join实现SQL中的in查询,0.13版本之后,Hive已经支持in查询。

十六,Hive的函数:UDF、UDAF、UDTF的区别?

  • UDF(User-Defined-Function): 单行进入,单行输出;如lower,case
  • UDAF(User-Defined Aggregation Function): 多行进入,单行输出,如count,sum
  • UDTF(User-Defined Table-Generating Functions): 单行输入,多行输出,lateral view explore()

十七,对Hive桶表的理解?

分桶的原理:

  • 桶表是对数据进行按照分桶字段哈希取值,然后放到不同文件中存储。
  • 数据加载到桶表时,会对字段取hash值,然后与桶的数量取模。把数据放到对应的文件中。物理上,每个桶就是表(或分区)目录里的一个文件,一个作业产生的桶(输出文件)和reduce任务个数相同。
  • 桶表专门用于抽样查询,是很专业性的,不是日常用来存储数据的表,需要抽样查询时,才创建和使用桶表。

分桶和分区的区别:

  • 分区是将不同文件进行归档,体现在文件夹上,不同分区是不同文件夹
  • 分桶体现在文件上,不同的桶是不同的文件
  • 分区字段不在表的schema中
  • 分桶字段在表的schema中

十八,Hive优化

1,Fetch抓取

优化原理:

Fetch抓取是指,Hive中对某些情况的查询可以不必使用MapReduce计算。例如:SELECT * FROM employees;在这种情况下,Hive可以简单地读取employee对应的存储目录下的文件,然后输出查询结果到控制台。

第一种Fetch(全文搜索,limit,字段,不带where条件)启用:

在hive-default.xml.template文件中hive.fetch.task.conversion默认是more,老版本hive默认是minimal,该属性修改为more以后,在全局查找、字段查找、limit查找等都不走mapreduce。

<property>
    <name>hive.fetch.task.conversion</name>
    <value>more</value>
    <description>
      Expects one of [none, minimal, more].
      Some select queries can be converted to single FETCH task minimizing latency.
      Currently the query should be single sourced not having any subquery and should not have
      any aggregations or distincts (which incurs RS), lateral views and joins.
      hive.fetch.task.conversion
      0. none : disable hive.fetch.task.conversion
      1. minimal : SELECT STAR, FILTER on partition columns, LIMIT only
      2. more  : SELECT, FILTER, LIMIT only (support TABLESAMPLE and virtual columns)
    </description>
  </property>

hive.fetch.task.conversion这个属性有三个可选的值:

  • none:关闭fetch task优化
  • minimal:只在select *、使用分区列过滤、带有limit的语句上进行优化
  • more:在minimal的基础上更加强大了,select不仅仅可以是*,还可以单独选择几列,并且filter也不再局限于分区字段,同时支持虚拟列(别名)

第二种Fetch,聚合类,比如count:

hive.fetch.task.aggr对于没有group by的聚合查询,比如select count(*) from src,这种最终都会在一个reduce中执行,像这种查询,可以把这个置为true将将其转换为fetch task,这可能会节约一些时间。

<property>
  <name>hive.fetch.task.aggr</name>
  <value>false</value>
  <description>
    Aggregation queries with no group-by clause (for example, select count(*) from src) execute
    final aggregations in single reduce task. If this is set true, Hive delegates final aggregation
    stage to fetch task, possibly decreasing the query time.
  </description>
</property>

2,本地模式

开启本地模式:

set hive.exec.mode.local.auto=true;

原理:
本地模式的原理是不把作业提交到集群,直接在客户端执行,减少任务调度、网络传输等消耗。

当一个job满足如下条件才能真正使用本地模式:

  • 1.job的输入数据大小必须小于参数:hive.exec.mode.local.auto.inputbytes.max(默认128MB)
  • 2.job的map数必须小于参数:hive.exec.mode.local.auto.tasks.max(默认4)
  • 3.job的reduce数必须为0或者1

3,大小表join

老版本要求小表在左,因为左边的表会被全部加载到内存,太大容易内存溢出。

新版本中小表在左还是在右已经无关紧要了。