跳转至

Hive

简述hive

我理解的,hive 就是一款构建数据仓库的工具,它可以将结构化的数据映射为一张表,并且可以通过 SQL语句进行查询分析。本质上是将SQL转换为MapReduce 或者spark来进行计算,数据是存储在 hdfs上,简单理解来说 hive就是 MapReduce的一个客户端工具。

你可以说一下 HQL转换为 MR的任务流程吗?

首先客户端提交 HOL 以后,hive通过解析器将 SOL转换成抽象语法树,然后通过编译器生成逻辑执行计划,再通过优化器进行优化,最后通过执行器转换为可以运行的物理计划,比如MapReduce/spark,然后提交到yarn 上执行。 详细来说: 1. 首先客户端提交 HQL 以后,Hive 利用 Antlr 框架对 HQL 完成词法语法解析,将 HQL 转换成抽象语法树 2. 然后遍历AST,将其转换成queryblock查询块,可以理解为最小的查询执行单元,比如 where 3. 然后遍历查询块,将其转换为操作树,也就是逻辑执行计划然后使用优化器对操作树进行逻辑优化,源码中会遍历所有的优化方式,比如 mapjoin,谓词下推等,来达到减少 MapReduce Job,减少shuffle 数据量的目的 4. 最后通过执行器将逻辑执行计划转换为物理执行计划(MR到这就结束了)(Tez和Spark还需要使用物理优化器对任务树进行物理优化),提交到hadoop集群运行

你可以说一下hive的元数据保存在哪里吗?

默认是保存在 java 自带的 derby数据库,但是这有一个缺点:derby 数据库不支持并发,也就是说不能同时两个客户端去操作derby数据库,因此通常情况下,都会配置一个mysql去存放元数据

hive 和传统数据库之间的区别

我认为主要有三点的区别:

  1. 数据量,hive 支持大规模的数据计算,mysql支持的小一些数据更新快不快,hive 官方是不建议对数据进行修改的,因为非常的慢.这一点我也测试过,而mysql经常会进行数据修改,速度也挺快的
  2. hive 大多数延迟都比较高的,mysql会低一些,当然这也与数据规模有关,数据规模很大的时候,hive不一定比mysql慢
  3. 为什么处理小表延迟比较高:因为hive 计算是通过 MapReduce,而MapReduce 是批处理,高延迟的。Hive的优势在于处理大数据,对于处理小数据是没有优势的

hive 的内部表和外部表的区别

从建表语句来看,加上了external关键字修饰的就是外部表,没加的就是内部表

我认为主要有两点的区别:

内部表的数据由 hive 自身管理,外部表的数据由hdfs管理 删除内部表的时候,元数据和原始数据都会被删除,而删除外部表的时候仅仅会删除元数据,原始数据不会被删除 使用场景:通常都会建外部表,因为一个表通常要多个人使用,以免删除了,还可以找到数据,保证了数据安全

hive 的 join 底层实现

首先 hive 的 join 分为 common join 和 map join,common join 就是 join 发生 在 reduce 端,map join 就是 join 发生在 map 端

common join:

分为三个阶段:map阶段,shutle阶段,reduce阶段

map阶段:对来自不同表的数据打标签,然后用连接字段作为key,其余部分和标签作为value,最后进行输出 shuffle 阶段:根据key的值进行hash,这样就可以将key 相同的送入一个reduce中 reduce 阶段:对来自不同表的数据进行join 操作就可以了

map join:

首先它是有一个适用前提的,适用于小表和大表的join 操作 小表多小为小呢?所以就有了一个参数进行配置:hive.mapjoin.smalltable.filesize-25M 它的原理是将小表复制多份,让每个maptask内存中存在一份,比如我可以存放到 HashMap 中,然后join 的时候,扫描大表,对于大表中的每条记录 key/value,在HashMap中查找是否有相同的key的记录,如果有,则 join 连接后输出即可,因为这里不涉及reduce 操作。 0.7 版本之后,都会自动转换为 mapjoin,如果之前的版本,我们配置个参数就可以了:hive.auto.convert.join=true

Order By 和 Sort By 的区别

distribute by:将数据根据by的字段散列到不同的reduce中cluster by:当 distribute by 和 sort by 字段相同的时候,就等价于 cluster by,但是排序只能是升序 order by: 全局排序,只有一个reducer,缺点:当数据规模大的时候,就会需要很长的计算时间 sort by:分区排序,保证每个reducer内有序,一般结合distribute by来使用使用场景:在生产环境中,orderby用的比较少,容易导致OOM;一般使用distribute by+sort by

行转列和列转行函数

JSON 解析函数:

  1. get json object:每次只能返回 json 对象中的一列值 selectget json object(data,'$.movie") as movie from json;

2.json tuple:每次可以返回多列的值 select b.b movie,b.b rate,b.b timeStamp, b.b uidfrom json lateral view json tuple(json.data,'movie','rate",'timeStamp','uid') b as b movie.b rate,b timeStamp, b uid;

如果是json 数组的话,那么就不能直接使用上述的操作,我们可以先使用regexp_replace方法进行字符串的替换,将它处理成多个ison,然后再使用上述的方法就可以了URL解析函数:HOSTOUERY

1.parse url:一对

2.parse url tuple:一对多

常见的行转列包括:一般的聚合函数,比如max,min,sum;还有汇总函数比如 collect list, collect set

常见的列转行就是:explode函数(jsontuple函数),只能传入array或者map 的数据,将它拆分成多行,一般会和1ateral view 一起使用

SELECT movie, category name FROM movie info lateral VIEWexplode(split(category,",")) movie info tmp AS category _name

窗口函数:

Rank:

rank():排序相同的时候,排名会重复,总数不变

dense rankO):排序相同的时候,排名会重复,总数减少row number():排序相同的时候,排名不会重复,总数不变lag(col,n,default):返回往上移n行的数据,不存在则返回 defaultlead(col,n,default):返回往下移n行的数据,不存在则返回 defaultfirst value(col):取分组内排序后,第一个值

last value(col):取分组内排序后,最后一个值

over 用法:首先通过over来指定窗口的特性,比如可以传入partitionby(分组),orderby(排序),rowsbetween..and..指定窗口的范围

CURRENTROW:当前行

nPRECEDING/FOLLOWING:往前/后行数据UNBOUNDEDPRECEDING/FOLLOWING 表示从前面的起点/到后面的终点

默认是 rows between UNBOUNDED PRECEDING and current row

自定义过UDF、UDTF函数吗

1.自定义函数

(1)自定义 UDF:

继承 UDF

重写evaluate方法

自定义 UDTF:

继承 GenericUDTF

重写3个方法:initialize,process,close

2.打成iar包,上传到服务器中

3.执行命令:addjar"路径",目的是将jar 添加到 hive中

4.注册临时函数:createtemporaryfunction 函数名 as"自定义函数全类名"

hive小文件过多怎么解决

首先我说一下为什么会产生小文件呢,hive中产生小文件,就是在向表中导入数据的时候,通常来说,我们在生产环境下,一般会使用insert+select的方式导入数据,这样会启动MR 任务,那么reduce有多少个就会输出多少个文件,也就是说insert每执行一次啊,就至少会生成一个文件,有些场景下,数据同步可能每10 分钟就会执行一次,这样就会产生大量的小文件。

然后我再说一下为什么要解决小文件呢,不解决不行吗? 首先对于hdfs来说,不适合存储大量的小文件,文件多了,namenode 需要记录元数据就非常大,就会占用大量的内存,影响hdfs性能 存储;对于hive来说,每个文件会启动一个maptask来处理,这样也会浪费资源计算.

最后我说一下怎么解决,使用hive自带的concatenate命令合并小文件,但是它只支持recfile和 orc 存储格式,也可以在MR过程中合并小文件 - map前 设置inputformat 为combinehiveinputformat:在 map 的时候会把多个 文件作为一个切片输入 - map后,reduce前 map输出的时候合并小文件 hive.merge.mapfiles - reduce后 reduce输出的时候合并小文件 hive.merge.mapredfiles 或者 直接设置少一点的reduce数量 mapreduce.job.reduces 也可以使用hadoop的archive归档方式

Hive 优化

建表优化: ◼ 分区表:减少全表扫描,通常查询的时候先基于分区过滤,再查询 ◼ 分桶表:按照join字段进行分桶,join的时候就不会全局join,而是桶 与桶之间进行join ◼ 合适的文件格式:公司中默认采用的是ORC的存储格式,这样可以降低 存储空间,内部有两个索引(行组索引和布隆过滤器索引)的东西,可 以加快查询速度 ◆ 我知道的hive的文件存储格式有textFile,sequenceFile,ORC,Parquet; 其中textFile 为 hive 的默认存储格式,它和sequenceFile一样都是基 于行存储的,ORC和Parquet都是基于列存储的。sequenceFile、ORC 和Parque 文件都是以二进制的方式存储的。 ◼ 合适的压缩格式:减少了IO读写和网络传输的数据量,比如常用的LZO (可切片)和snappy ⚫ 语法优化: ◼ 单表查询优化: ◆ 列裁剪和分区裁剪:如果 select * 或者不指定分区,全列扫描和全 表扫描效率都很低(公司规定了必须指定分区,select *没有明确规 定) ◆ group by 优化: ⚫ 开启map端聚合 ⚫ 开启负载均衡:这样生成的查询计划会有两个 MR Job,一个是 局部聚合(加随机数),另外一个是全局聚合(删随机数) ◆ SQL写成多重模式:有多条SQL重复扫描一张表,那么我们可以写 成 from 表 select... select... ◼ 多表查询优化: CBO优化:选择代价最小的执行计划;自动优化 HQL 中多个 Join 的顺序,并选择合适的 Join 算法 ⚫ set hive.cbo.enable = true(默认开启) ◆ 谓词下推:将 SQL 语句中的 where 谓词逻辑都尽可能提前执行, 减少下游处理的数据量。 ⚫ hive.optimize.ppd = true(默认开启) ◆ MapJoin:将join双方比较小的表直接分发到各个Map进程的内存 中,在Map进程中进行join操作,这样就不用进行Reduce,从而提 高了速度 ⚫ set hive.auto.convert.join=true(默认开启) ⚫ set hive.mapjoin.smalltable.filesize=25000000(默认 25M 以下是小 表) ◆ SMB Join:分桶join,大表转换为很多小表,然后分别进行join,最 后union 到一起 ⚫ job优化: ◼ map优化 ◆ 复杂文件增加map数 ◆ 小文件合并 ◆ map端聚合 ◆ 推测执行 ◼ reduce优化 ◆ 合理设置reduce: ⚫ 为什么reduce的数量不是越多越好? ◼ 过多的启动和初始化 reduce 也会消耗时间和资源; ◼ 另外,有多少个 reduce,就会有多少个输出文件,如果生成 了很多个小文件,那么如果这些小文件作为下一个任务的输 入,则也会出现小文件过多的问题; ◆ 推测执行 ◼ 任务整体优化: ◆ fetch抓取:Hive 中对某些情况的查询可以不必使用 MapReduce 计 算【全局查找、字段查找、limit 查找】 hive.fetch.task.conversion=more ◆ 小数据集启用本地模式 hive.exec.mode.local.auto=true ◆ 多个阶段并行执行 set hive.exec.parallel=true ◆ JVM重用:针对小文件过多的时候使用

Hive的实现逻辑,为什么处理小表延迟比较高

因为其计算是通过MapReduce,MapReduce是批处理,高延迟的。小文件也要执行MapReduce。Hive的优势在于处理大数据,对于处理小数据没有优势

如何理解Hive,为什么使用Hive

hive就是一款构建数据仓库的工具,它可以将结构化的数据映射为一张表,并且可以通过SQL语句进行查询分析。本质上是将SQL转换为MapReduce或者spark来进行计算,数据是存储在hdfs上,简单理解来说hive就是MapReduce的一个客户端工具。

Hive怎么判断是数据倾斜呢

某个reduce task,卡在99%半天不动,任务超时被杀掉 通过时间判断:如果某个reduce的时间比其他reduce时间长的多。 通过任务Counter判断:Counter会记录整个job以及每个task的统计信息,可以看输入记录数和输出字 符数

Hive数据倾斜怎么解决

null值过滤,如果大key是无意义的脏数据,直接过滤掉。 Skew-GroupBy 优化 Skew-GroupBy 是 Hive 提供的一个专门用来解决分组聚合导致的数据倾斜问题的方案。 其原理是启动两个 MR 任务,第一个 MR 按照随机数分区,将数据分散发送到Reduce, 并完 成部分聚合,第二个 MR 按照分组字段分区,完成最终聚合。(先分区聚合再最终聚合) 使用 Map Join 多用于大表Join小表 ,Join 操作仅在 Map 端就能完成,没有 Shuffle 操作,没有Reduce 阶 段,自然不会产生 Reduce 端的数据倾斜 使用 SkewJoin 会将一个join sql 分为两个job。给倾斜比较严重的key单独开一个job

你理解的hive是什么框架?

hive是一个构建在 Hadoop 上的数据仓库工具 (框架)。 可以将结构化的数据文件映射成一张数据表,并可以使用类sql的方式来对这样的数据文件进行读,写以及管理(包括 元数据)。 这套HIVE SQL 简称 HQL。 hive的执行引擎可以是MR、spark、tez。 Hive的本质是将HQL转换成 MapReduce 任务,完成整个数据的分析查询,减少编写MapReduce的复杂度。

HQL执行很慢,怎么排查?

  • 确定任务卡住的 stage
  • 通过 jobname 确定 stage:一般 Hive 默认的 jobname 名称会带上 stage 阶段
  • 确定SQL执行代码
  • 结合执行计划,则可以判断出是执行哪段代码导致的卡顿
  • 分析原因
  • 举例说比如分析出是数据倾斜导致的SQL执行很慢
    • 追问:怎么判断是数据倾斜导致的呢
  • 解决问题
  • 接着上面,这里就回答Hive数据倾斜怎么解决

Hive怎么判断是数据倾斜呢

某个reduce task,卡在99%半天不动,任务超时被杀掉

通过时间判断:如果某个reduce的时间比其他reduce时间长的多。

通过任务Counter判断:Counter会记录整个job以及每个task的统计信息,可以看输入记录数和输出字符数

Hive数据倾斜怎么解决

  • null值过滤,如果大key是无意义的脏数据,直接过滤掉。
  • Skew-GroupBy 优化
  • Skew-GroupBy 是 Hive 提供的一个专门用来解决分组聚合导致的数据倾斜问题的方案。
  • 其原理是启动两个 MR 任务,第一个 MR 按照随机数分区,将数据分散发送到Reduce, 并完成部分聚合,第二个 MR 按照分组字段分区,完成最终聚合。(先分区聚合再最终聚合
  • 使用 Map Join
  • 多用于大表Join小表 ,Join 操作仅在 Map 端就能完成,没有 Shuffle 操作,没有Reduce 阶段,自然不会产生 Reduce 端的数据倾斜
  • 使用 SkewJoin
  • 会将一个join sql 分为两个job。给倾斜比较严重的key单独开一个job

hive和spark的区别

本质上来说,

hive 是基于Hadoop的一个构建数据仓库的工具,用来进行数据提取、转化、加载,并且它定义了类SQL语言HQL,允许熟悉SQL的用户查询数据。

Spark 是专为大规模数据处理而设计的快速通用的计算引擎,spark 的主要实现目的就是优化mapreduce 执行

HiveSQL与SparkSQL的区别

  • 执行引擎
  • HiveSQL 的默认执行引擎是mapreduce,可以通过配置更换成spark,即 hive on spark
  • SparkSQL 本身属于spark生态群的一部分,基于RDD工作
  • 性能
  • hiveSQL默认解析成mapreduce任务计算,中间结果需要落盘,以进程的方式运行,性能较差
  • sparkSQL将SQL转换成spark的RDD或DataFrame操作,利用内存计算,以线程的方式运行,性能较好
  • 优化器
  • hiveSQL使用的是基于代价的优化器,即CBO
  • sparkSQL会使用Catalyst优化器

hive on spark大体与SparkSQL结构类似,只是SQL解析器不同,但是计算引擎都是spark!

Hive On Spark引擎的特点

窗口化函数怎么多行变一行

一行变多行: LATERAL VIEW explode (split(col_name,','))

多行变一行:collectset() 去重;collectlist() 不去重

讲讲几个udf的区别

  • udf:一对一,输入一行输出一行
  • udaf:多对一,用户自定义聚合函数
  • udtf:一对多,用户自定义生成函数

hive怎样引入 udf 的

  • (1)pom.xml 增加 hive-exec 依赖
  • (2)编写Java ,继承 UDF,实现方法 evaluate
  • (3)打包上传服务器lib下,并赋权
  • (4)进入hive 通过add jar 命令导入jar包
  • (5)创建临时函数指定jar包
  • (6)运行自定义UDF

hive遇到过慢查询吗?如何解决(排查)?

  • 确定任务卡住的 stage
  • 通过 jobname 确定 stage:一般 Hive 默认的 jobname 名称会带上 stage 阶段,webUI上面可以直接看
  • 确定SQL执行代码
  • 结合执行计划,则可以判断出是执行哪段代码导致的卡顿
  • 分析原因
  • 举例说比如分析出是数据倾斜导致的SQL执行很慢
  • 追问:怎么判断是数据倾斜导致的呢
    • 某个reduce的时间比其他reduce时间长的多。
  • 解决问题
  • 接着上面,这里就回答Hive数据倾斜怎么解决
  • 如果大key无意义,直接过滤
  • Skew-GroupBy 优化,原理是启动两个MR任务先分区聚合再最终聚合
  • 使用 Map Join,大表join小表,减少shuffle操作
  • 使用 Skew Join,给倾斜比较严重的key单独开一个job

hive的内外部表区别

对比项 内部表 外部表
Hive 管理范围 元数据、实际的表数据 元数据
建表语句 不需要 external 关键字修饰 需要 external 关键字修饰
drop 删除表后果 删除元数据和实际的表数据 只删除元数据,实际的表数据保留
存储路径 一般在默认位置存储数据 一般搭配 location 指定数据存放位置
表结构和分区更改的区别 自动同步到元数据 需要修复表

hive json函数

两个内置函数

getjsonobject 语法:get_json_object(json_string, '$.column')

json_tuple 语法:json_tuple(json_string, column1, column2, column3 ...)

hive开窗函数

开窗函数(Window Function)也叫窗口函数,它可以在当前行所在的窗口范围内进行计算,不会像GROUP BY那样改变行数,而是为每一行输出计算结果,常用于分组排序、累计求和、移动平均等场景。

  • 开窗函数基本语法
函数名() OVER([PARTITION BY 分组列] [ORDER BY 排序列] [ROWS BETWEEN 起始行 AND 结束行])
  • OVER():定义窗口的范围,所有开窗函数都需要这个关键字
  • PARTITION BY:按照指定字段对数据进行分区(分组),开窗函数在每个分区内独立计算,不跨分区计算
  • ORDER BY:在分区内对数据进行排序,决定计算顺序
  • ROWS BETWEEN控制窗口的范围,即当前计算要包含哪些行

  • 窗口范围说明

关键字 含义
UNBOUNDED PRECEDING 分区内从第一行开始
UNBOUNDED FOLLOWING 到分区内最后一行结束
CURRENT ROW 当前行开始/结束
n PRECEDING 当前行往前n行
n FOLLOWING 当前行往后n行

常用示例: - ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW:从第一行到当前行(累计求和常用) - ROWS BETWEEN 2 PRECEDING AND CURRENT ROW:最近3行(包含当前行),用于移动平均 - ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING:整个分区所有行

默认窗口范围: - 如果指定了 ORDER BY,默认是 ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW - 如果没有指定 ORDER BY,默认是 ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING


  • 开窗函数分类

  • 聚合开窗函数 在窗口范围内执行聚合计算:

函数 说明
SUM(col) 窗口内求和
COUNT(col) 窗口内计数
AVG(col) 窗口内求平均
MAX(col) 窗口内求最大值
MIN(col) 窗口内求最小值

示例:求每个部门每个月的累计销售额

SELECT 
  dept,
  month,
  sales,
  SUM(sales) OVER (PARTITION BY dept ORDER BY month) AS cum_sales
FROM sales_table;

  1. 排序开窗函数 对分区内数据排序,生成排名:
函数 相同值排名 排名是否跳号 总数 适用场景
row_number() 不重复,依次递增 不跳号 不减少 取TopN、去重
rank() 相同值同排名 跳号 不变 竞赛排名
dense_rank() 相同值同排名 不跳号 减少 百分等级

举例对比(数据:100, 100, 90, 80):

分数 row_number rank dense_rank
100 1 1 1
100 2 1 1
90 3 3 2
80 4 4 3

典型应用:每个部门薪资Top3:

SELECT * FROM (
  SELECT 
    dept,
    name,
    salary,
    row_number() OVER (PARTITION BY dept ORDER BY salary DESC) AS rn
  FROM employee
) t WHERE rn <= 3;

  1. 分析开窗函数 用于数据偏移、取值等分析:
函数 说明
LAG(col, n, default) 获取当前行往前第n行的col值,找不到返回default,常用于计算同比环比
LEAD(col, n, default) 获取当前行往后第n行的col值,找不到返回default
FIRST_VALUE(col) 窗口内排序后第一个
LAST_VALUE(col) 窗口内排序后最后一个
NTILE(n) 将分区内数据分为n份,返回当前行所在的编号,常用于分组取前百分之几

LAG使用示例(计算环比增长率):

SELECT 
  month,
  sales,
  LAG(sales, 1) OVER (ORDER BY month) AS last_month_sales,
  (sales - LAG(sales, 1) OVER (ORDER BY month)) / LAG(sales, 1) OVER (ORDER BY month) AS rate
FROM sales_table;

NTILE使用示例(取前30%数据):

SELECT * FROM (
  SELECT 
    *,
    NTILE(10) OVER (ORDER BY score DESC) AS nt
  FROM student
) t WHERE nt <= 3;

  • 开窗函数 vs GROUP BY

  • GROUP BY:分组后聚合,行数减少为分组数,每组一行

  • 开窗函数:在窗口内计算,行数不变,原表每一行都输出计算结果,更灵活

Hive内部表和外部表的区别?分区和分桶的使用场景?

如何用Hive SQL统计近7天每小时的平均请求量?(给出表结构和SQL)

你提到用Hive分析数据,如何优化一个执行缓慢的Hive SQL查询?

  • 参考回答:
    • 检查数据倾斜:通过DISTRIBUTE BY对Key重分布;
    • 分区裁剪:避免全表扫描,利用分区字段过滤;
    • 小文件合并:使用ALTER TABLE CONCATENATE减少Map任务数。

评论