当前位置: 首页 > news >正文

大数据组件-Hive

1.Hive概念

Hive 是基于 Hadoop 的数据仓库工具,用于处理大规模结构化数据。它将 SQL 查询转换为 MapReduce 任务,简化了分布式计算操作。Hive 适合离线批处理场景,支持数据存储、查询和分析。

2.Hive核心特性

  • 类 SQL 语法(HQL):支持类似 SQL 的查询语言,降低学习成本。
  • 数据存储:数据以表形式存储在 HDFS 中,支持文本、Parquet、ORC 等格式。
  • 元数据管理:通过元存储(Metastore)管理表结构、分区等信息。
  • 扩展性:支持自定义函数(UDF)、SerDe(序列化/反序列化)等扩展功能。

3.Hive 的架构组件

  • Driver:接收 HQL 查询,生成执行计划并协调任务执行。
  • Compiler:解析 HQL,优化逻辑计划并转换为物理计划(如 MapReduce)。
  • Metastore:存储表定义、分区等元数据,通常使用关系型数据库(如 MySQL)。
  • Execution Engine:默认使用 MapReduce,也可配置为 Tez 或 Spark。

4.Hive 的数据模型

  • 表(Table):逻辑概念,数据存储在 HDFS 的目录中。
  • 分区(Partition):按列值划分数据,加速查询(如按日期分区)。
  • 分桶(Bucket):对数据哈希分片,优化 JOIN 和采样效率。

5.Hive的局限性

  • 延迟高:批处理模式不适合实时查询。
  • 事务支持有限:早期版本不支持 ACID,新版本通过 Hive 3.x 改进。

6.Hive内部表和外部表

  • 内部表(MANAGED_TABLE):Hive 全权管理数据和元数据
  • 外部表(EXTERNAL_TABLE):Hive 只管理元数据,数据由 HDFS 管理

7.Hive元数据存储

默认有自己的数据开Derby,但是生产中常用mysql

hive存储的元数据是描述数据信息的数据,比如:

数据库、表名

字段名、字段类型

表是内部表还是外部表

分区信息(dt=20260401 这些)

数据在 HDFS 上的存储路径

分桶信息、存储格式(ORC/Parquet)

SerDe 信息

8.Hive的分区和分桶

分区

  • 概念:

分区是一种将大型表的数据根据特定维度(通常是日期、地区、类别等列)物理划分到不同子目录中的技术。

  • 目的:

优化查询性能: 当查询语句的WHERE子句包含分区键时,Hive 可以只扫描相关分区的目录,避免全表扫描,显著减少 I/O 和数据量。这称为分区裁剪

数据管理: 便于按分区加载、删除或归档数据。

-- 创建分区表 CREATE TABLE logs ( id INT, user_id STRING, event_type STRING ) PARTITIONED BY (event_date STRING, region STRING) STORED AS ORC;
  • 注意事项:

避免分区过多(如按天分区持续多年可能导致成千上万分区),过多的小文件会降低 NameNode 性能和查询效率。

分区键应选择常用于WHERE过滤的列,且基数不宜过高。

分桶

  • 概念:

分桶是将一个表或分区内的数据进一步划分为固定数量的文件(桶)。划分规则基于对分桶键(一列或多列)进行哈希取模计算。例如,一个分区内按user_id分成 4 个桶,Hive 会根据hash(user_id) % 4的结果将数据放入对应的桶文件。

  • 目的:

高效采样:可以快速对特定桶进行随机采样,用于数据预览或测试。

优化 JOIN:如果两个表都以相同方式对 JOIN 键分桶,且桶数量相同或成倍数关系,Hive 可以执行高效的桶映射 JOIN。只需将对应桶的数据进行 JOIN,无需对整个表进行 Shuffle 和 Reduce。

优化聚合:对于GROUP BY分桶键的查询,可以更快完成。

更均匀的数据分布:有助于避免数据倾斜。

-- 创建分桶表 (通常先分区再分桶) CREATE TABLE user_actions ( user_id INT, action STRING, timestamp BIGINT ) PARTITIONED BY (event_date STRING) CLUSTERED BY (user_id) INTO 4 BUCKETS STORED AS ORC;

分区 vs 分桶 总结

9.Hivesql的执行流程

  • 解析与编译:首先,SQL 语句会被 Client 提交到 Driver。Driver 内部的解析器 (Parser) 会将 SQL 转换成抽象语法树 (AST)。然后,编译器 (Compiler)会去连接 Metastore,获取 user_log 表的元数据,进行语义分析,并将 AST 编译成一个由逻辑操作符组成的 DAG(有向无环图),也就是逻辑执行计划。
  • 优化:接着,优化器 (Optimizer) 会对这个逻辑计划进行优化。针对写的 WHERE dt='2023-11-25' 这个条件,优化器会执行分区裁剪 (Partition Pruning),确保计算任务只去扫描 dt=2023-11-25 这个分区目录下的文件,极大地减少了 IO。优化后会生成物理执行计划。
  • 提交与执行:执行器 (Executor) 将物理计划(一系列的 MapReduce 或 Spark 任务)提交给 YARN 的 ResourceManager (RM)。
  • 资源分配与计算:RM 会在集群中找一个 NodeManager (NM) 启动 ApplicationMaster (AM)。AM 负责向 RM 申请计算所需的资源(Container),然后在这些 Container 里启动 Map 和 Reduce Task。这些 Task 会去 HDFS 上读取指定分区下的数据文件进行计算。
  • 返回结果:所有 Task 计算完成后,最终的结果会汇总,由 Driver 获取并返回到我的客户端屏幕上。”

10.Hive的相关调优

切记:hive只是一个工具,提供类似sql的操作方式,本质是运行MR程序,因此,调优是在优化MR,而不是把mysql的优化拿过来。

主要从四个方面来说:

hive的建表设计,Hivesql本身的优化,Hive配置参数, 底层引擎MR方面的调整

调优注意事项

  1. 对于大数据计算引擎来说:数据量大不是问题,数据倾斜是个问题。
  2. Hive 的复杂 HQL 底层会转换成多个 MapReduce Job 并行或者串行执行,Job 数比较多的作业运行效率相对比较低,比如即使只有几百行数据的表,如果多次关联多次汇总,产生十几个 Job,耗时很长。原因是 MapReduce 作业初始化的时间是比较长的。
  3. 在进行 Hive 大数据分析时,常见的聚合操作比如 sum, count, max, min, UDAF 等,不怕数据倾斜问题,MapReduce 在 Mapper 阶段的预聚合操作,使数据倾斜不成问题。
  4. 好的建表设计,模型设计事半功倍。
  5. 设置合理的 MapReduce 的 Task 并行度,能有效提升性能。比如,10w + 数据量级别的计算,用 100 个reduceTask,那是相当的浪费,1 个足够,但是如果是亿级别的数据量,那么 1 个 Task 又显得捉襟见肘。
  6. 了解数据分布,自己动手解决数据倾斜问题是个不错的选择。这是通用的算法优化,但算法优化有时不能适应特定业务背景,开发人员了解业务,了解数据,可以通过业务逻辑精确有效的解决数据倾斜问题。
  7. 数据量较大的情况下,慎用 count (distinct),group by 容易产生倾斜问题。
  8. 对小文件进行合并,是行之有效的提高调度效率的方法,假如所有的作业设置合理的文件数,对任务的整体调度效率也会产生积极的正向影响。
  9. 优化时把握整体,单个作业最优不如整体最优。
  10. 优化 MySQL 的 SQL 优化技巧,是不适用在 Hive 的。

(1)hive的建表设计层面

①利用分区表优化

当一个hive表查询的大多数情况下都需要根据某个字段进行筛选时,那么非常时候将该字段作为分区字段进行分区

②利用分桶表优化

分桶表最大的作用就是帮助我们提高join查询以及采样。

select a.*, b.* from a join b on a.id = b.id;

解决方案:

  1. 两张表都得按照这个连接字段来进行分桶
  2. 分桶数量要成倍数关系

③选择合适的存储格式

  • 原始数据,一般来说,都是普通文本格式
  • 计算的结果数据
    • 如果这种结果数据,通常还要作为另外一种计算的输入,那么可以让当前这个结果数据的格式易于被读取(序列化文件格式可用)
    • 如果这种结果数据,就是最终的结果了,那么看数据量的大小关系:
      • 如果比较大:可以考虑压缩
      • 如果不是特别大:直接普通文本格式,甚至存储在 RDBMS
  • 计算引擎中应用程序在执行的时候:
    • 中间临时数据:执行引擎的特性:列式存储 + 序列化存储文件格式

第一种: TextFile

  1. 存储方式:行存储。默认格式,如果建表时不指定默认为此格式。
  2. 每一行都是一条记录,每行都以换行符 “\n” 结尾。数据不做压缩时,磁盘会开销比较大,数据解析开销也比较大。
  3. 可结合 Gzip、Bzip2 等压缩方式一起使用(系统会自动检查,查询时会自动解压),推荐选用可切分的压缩算法。

第二种: Sequence File

  1. 一种 Hadoop API 提供的二进制文件,使用方便、可分割、可压缩的特点。
  2. 支持三种压缩选择:NONE、RECORD、BLOCK。RECORD 压缩率低,一般建议使用 BLOCK 压缩。

第三种: RC File

  1. 存储方式:数据按行分块,每块按照列存储 。
    • A、首先,将数据按行分块,保证同一个 record 在一个块上,避免读一个记录需要读取多个 block。
    • B、其次,块数据列式存储,有利于数据压缩和快速的列存取。
  2. 相对来说,RCFile 对于提升任务执行性能提升不大,但是能节省一些存储空间。可以使用升级版的 ORC 格式。

第四种: ORC File

  1. 存储方式:数据按行分块,每块按照列存储 。
  2. Hive 提供的新格式,属于 RCFile 的升级版,性能有大幅度提升,而且数据可以压缩存储,压缩快,快速列存取。
  3. ORC File 会基于列创建索引,当查询的时候会很快。

第五种:Parquet File

  1. 存储方式:列式存储。
  2. Parquet 对于大型查询的类型是高效的。对于扫描特定表格中的特定列查询,Parquet 特别有用。Parquet 一般使用 Snappy、Gzip 压缩。默认 Snappy。
  3. Parquet 支持 Impala 查询引擎。
  4. 表的文件存储格式尽量采用 Parquet 或 ORC,不仅降低存储量,还优化了查询,压缩,表关联等性能。

④选择合适的压缩格式

压缩格式是否可拆分是否自带压缩率速度是否 hadoop 自带
gzip很高比较快
lzo比较高很快否,要安装
snappy比较高很快否,要安装
bzip2最高

(2)Hive语法和运行参数

1. 查看 Hive 执行计划

Hive 的 SQL 语句在执行之前需要将 SQL 语句转换成 MapReduce 任务,因此需要了解具体的转换过程,可以在 SQL 语句中输入如下命令查看具体的执行计划。

查看执行计划,添加 extended 关键字可以查看更加详细的执行计划

explain [extended] query

例子:

explain select department, count(*) as total from student where age >= 18 group by department order by total desc limit 3;

关于 Hive 的执行计划中的 Operator 的概念: (逻辑执行计划: Operator Tree)

select ... from ... where ... group by ... having ... order by ..... limit .....

一条 Hive SQL 写完,底层会被拆成一串 “操作步骤”,这一串步骤就叫 Operator Tree(算子树)

每个节点(例如select,group by)都是一个Operate

2. 列裁剪

列裁剪就是在查询时只读取需要的列,分区裁剪就是只读取需要的分区。当列很多或者数据量很大时,如果 select * 或者不指定分区,全列扫描和全表扫描效率都很低。

Hive 在读数据的时候,可以只读取查询中所需要用到的列,而忽略其他的列。这样做可以节省读取开销:中间表存储开销和数据整合开销。

set hive.optimize.cp = true; ## 列裁剪,取数只取查询中需要用到的列,默认是true

3. 谓词下推

将 SQL 语句中的 where 谓词逻辑都尽可能提前执行,减少下游处理的数据量。对应逻辑优化器是PredicatePushDown

set hive.optimize.ppd=true; ## 默认是true

示例程序:

select a.*, b.* from a join b on a.id = b.id where b.age > 20; select a.*, c.* from a join (select * from b where age > 20) c on a.id = c.id;

4. 分区裁剪

列裁剪就是在查询时只读取需要的列,分区裁剪就是只读取需要的分区。当列很多或者数据量很大时,如果select *或者不指定分区,全列扫描和全表扫描效率都很低。

在查询的过程中只选择需要的分区,可以减少读入的分区数目,减少读入的数据量。

Hive 中与分区裁剪优化相关的规则:

set hive.optimize.pruner=true; ## 默认是true

在 HiveSQL 解析阶段对应的规则是ColumnPruner逻辑优化器。

示例:

select * from student where department = "AAAA";

5. 合并小文件

大数据技术组件最怕的就是两个事儿:

  1. 存储组件:海量小文件SQL 示例:1000000M = 100000 × 10M→ 100000 个小文件
  2. 计算组件:数据倾斜SQL 示例:1000000M = 100000 × 10M→ 100000 个小文件,但是其中有两个超级大

如果一个 MapReduce Job 碰到一堆小文件作为输入,一个小文件会启动一个 Task。

在 MR 编程模型中,提供了一个叫做CombineFileInputFormat的类:具备把一个节点甚至一个机架上的多个小文件,划分到同一个输入切片的能力。

Hive 的默认InputFormatTextInputFormat

Map 输入合并

在执行 MapReduce 程序的时候,一般情况是一个文件的一个数据分块需要一个mapTask来处理。但是如果数据源是大量的小文件,这样就会启动大量的mapTask

务,会浪费大量资源。可以将输入的小文件进行合并,从而减少mapTask任务数量。

Map 端输入、合并文件之后按照 block 的大小分割(默认) set hive.input.format=org.apache.hadoop.hive.ql.io.CombineHiveInputFormat; Map 端输入,不合 set hive.input.format=org.apache.hadoop.hive.ql.io.HiveInputFormat;
Map/Reduce 输出合并

大量的小文件会给 HDFS 带来压力,影响处理效率。可以通过合并 Map 和 Reduce 的结果文件来消除影响。

是否合并 Map 输出文件,默认值为 true set hive.merge.mapfiles=true; ## 是否合并 Reduce 端输出文件,默认值为 false set hive.merge.mapredfiles=true; ## 合并文件的大小,默认值为 256000000 = 256M set hive.merge.size.per.task=256000000; ## 每个 Map 最大分割大小 set mapred.max.split.size=256000000; ## 一个节点上 split 的最小值 set mapred.min.split.size.per.node=1; // 服务器节点 如果有多个节点,都是只有一个小文件,这种情况当中,意味着压根没合并 如果这个节点有 300 个 1M 的文件。指定的输入切片大小是:256M, 44M 的数据会传送给其他节点做合并 如果这个节点有 500 个 1M 的文件。指定的输入切片大小是:256M, 244M 的数据会传送给其他节点做合并 ## 一个机架上 split 的最少值 set mapred.min.split.size.per.rack=1; // 服务器机架

6.合理设置Maptask并行度

7.合理设置ReduceTask并行度

8.join优化

Join 优化整体原则:

  1. 优先过滤后再进行 Join 操作,最大限度的减少参与 join 的数据量(where 能用就用)
  2. 小表 join 大表,最好启动 mapjoin,hive 自动启用 mapjoin,小表不能超过 25M,可以更改
  3. Join on 的条件相同的话,最好放入同一个 job,并且 join 表的排列顺序从小到大:
    select a.*, b.*, c.* from a join b on a.id = b.id join c on a.id = c.i
  4. 如果多张表做 join,如果多个链接条件都相同,会转换成一个 Job
优先过滤数据

尽量减少每个阶段的数据量,对于分区表要用上分区字段的尽量使用,同时只选择后面需要使用到的列,最大限度的减少参与 Join 的数据量。

小表 join 大表原则

小表 join 大表的时应遵守小表 join 大表原则,原因是 join 操作的 reduce 阶段,位于 join 左边的表内容会被加载进内存,将条目少的表放在左边,可以有效减少发生内存溢出的几率。join 中执行顺序是从左到右生成 Job,应该保证连续查询中的表的大小从左到右是依次增加的。

使用相同的连接键

在 hive 中,当对 3 个或更多张表进行 join 时,如果 on 条件使用相同字段,那么它们会合并为一个 MapReduce Job,利用这种特性,可以将相同的 join on 放入一个 job 来节省执行时间。

尽量原子操作

尽量避免一个 SQL 包含复杂的逻辑,可以使用中间表来完成复杂的逻辑。

大表 Join 大表
  1. 空 key 过滤:有时 join 超时是因为某些 key 对应的数据太多,而相同 key 对应的数据都会发送到相同的 reducer 上,从而导致内存不够。此时我们应该仔细分析这些异常的 key,很多情况下,这些 key 对应的数据是异常数据,我们需要在 SQL 语句中进行过滤。
  2. 空 key 转换:有时虽然某个 key 为空对应的数据很多,但是相应的数据不是异常数据,必须要包含在 join 的结果中,此时我们可以表 a 中 key 为空的字段赋一个随机的值,使得数据随机均匀地分布到不同的 reducer 上。

9.启用 MapJoin

关于 Hive 调优中,“能用就用” 的原则和方法:

  1. where —— 能用就用
  2. mapjoin —— 资源允许的情况下
  3. 局部聚合 combiner —— 不改变业务结果的情况下

MapJoin 是将 join 双方比较小的表直接分发到各个 map 进程的内存中,在 map 进程中进行 join 操作,这样就不用进行 reduce 步骤,从而提高了速度。只有 join 操作才能启用 MapJoin。

# 是否根据输入小表的大小,自动将reduce端的common join 转化为map join,将小表刷入内存中。 # 对应逻辑优化器是MapJoinProcessor set hive.auto.convert.join = true; # 刷入内存表的大小(字节) 25M = 2G set hive.mapjoin.smalltable.filesize = 25000000; # hive会基于表的size自动的将普通join转换成mapjoin set hive.auto.convert.join.noconditionaltask=true; # 多大的表可以自动触发放到内层LocalTask中,默认大小10M set hive.auto.convert.join.noconditionaltask.size=10000000;

Hive 可以进行多表 Join。Join 操作尤其是 Join 大表的时候代价是非常大的。MapJoin 特别适合大小表 join 的情况。在 Hive join 场景中,一般总有一张相对小的表和一张相对大的表,小表叫 build table,大表叫 probe table。

Hive 在解析带 join 的 SQL 语句时,会默认将最后一个表作为 probe table,将前面的表作为 build table 并试图将它们读进内存。如果表顺序写反,probe table 在前面,引发 OOM 的风险就高了。在维度建模数据仓库中,事实表就是 probe table,维度表就是 build table。这种 Join 方式在 map 端直接完成 join 过程,消灭了 reduce,效率很高。而且 MapJoin 还支持非等值连接。

当 Hive 执行 Join 时,需要选择哪个表被流式传输(stream),哪个表被缓存(cache)。Hive 将 JOIN 语句中的最后一个表用于流式传输,因此我们需要确保这个流表在两者之间是最大的。如果要在不同的 key 上 join 更多的表,那么对于每个 join 集,只需在 ON 条件右侧指定较大的表。

也可以手动开启 mapjoin:

-- SQL方式,在SQL语句中添加MapJoin标记(mapjoin hint) -- 将小表放到内存中,省去shuffle操作 -- 在没有开启mapjoin的情况下,执行的是reduceJoin SELECT /*+ MAPJOIN(smallTable) */ smallTable.key, bigTable.value FROM smallTable JOIN bigTable ON smallTable.key = bigTable.key; /*+mapjoin(a,b,c)*/ /*+mapjoin(a)*/

10.Sort-Merge-Bucket(SMB) Map Join

它是另一种 Hive Join 优化技术,使用这个技术的前提是所有的表都必须是分桶表(bucket)和分桶排序的(sort)。分桶表的优化!

distribute by .... sort by ....

具体实现:

  1. 针对参与 join 的这两张做相同的 hash 散列,每个桶里面的数据还要排序
  2. 这两张表的分桶个数要成倍数。
  3. 开启 SMB join 的开关!

一些常见参数设置:

-- 当用户执行bucket map join的时候,发现不能执行时,禁止查询 set hive.enforce.sortmergebucketmapjoin=false; -- 如果join的表通过sort merge join的条件,join是否会自动转换为sort merge join set hive.auto.convert.sortmerge.join=true; -- 当两个分桶表 join 时,如果 join on的是分桶字段,小表的分桶数是大表的倍数时,可以启用 mapjoin 来提高效率。 -- bucket map join优化,默认值是 false set hive.optimize.bucketmapjoin=false; -- bucket map join 优化,默认值是 false set hive.optimize.bucketmapjoin.sortedmerge=false;
http://www.cnnetsun.cn/news/1737622.html

相关文章:

  • Office 365中的Entra ID for Education详细功能介绍
  • YOLOE官版镜像部署案例:中小企业低成本实现多模态目标分割
  • Qwen3-4B-Instruct-2507场景应用:用vLLM+Chainlit快速构建个人知识问答库
  • 数码管静态显示 0~9 任意数字
  • 零基础玩转esp32,快马平台ai生成带注释示例代码助新手快速入门
  • 数据库面试基础
  • Rust单元测试与集成测试实践:从理论到实战
  • 思源宋体CN:零成本构建专业级中文排版系统的全行业解决方案
  • 不只是协议流程图:用Python脚本模拟DisplayPort CR训练过程,理解CDR锁定的本质
  • 7个强力工具:Masa Mods中文汉化包让Minecraft模组说中文
  • 2026届毕业生推荐的五大降重复率助手推荐
  • 解锁期刊论文“通关秘籍”:好写作AI的神奇魔法
  • 告别L298N!用Arduino UNO和TB6612FNG驱动智能小车电机,保姆级接线与代码避坑指南
  • 5大突破掌握文件解析利器:从数据提取到跨领域创新
  • 香橙派上编译librealsense 2.55.1:网络依赖拉取失败与手动编译的实战避坑
  • SpringCloud Alibaba最新版避坑指南:如何优雅解决Nacos 9848端口占用问题
  • QuickBMS终极指南:5步掌握游戏资源提取与修改
  • 避坑指南:用Stata计算OP法TFP时,如何处理‘投资’变量与‘退出’判定?
  • 深入解析Redis Lettuce连接池在Windows环境下的TCP/IP保活机制优化
  • 像素自由:SRWE实现窗口分辨率精准控制的技术突破与行业应用
  • 2026年电缆故障定位仪市场深度解析:品牌影响力与厂家综合排名报告
  • 高效打造专业Power BI报表:30+主题模板的创新应用指南
  • Win11开机提示页面文件配置问题?3分钟搞定虚拟内存设置(附BitLocker关闭指南)
  • GORM实战:5分钟搞定PostgreSQL连接池配置(附Redis缓存最佳实践)
  • Kaggle上最火的3个水稻病害数据集实测:数据质量、标注细节全解析
  • Phi-4-mini-reasoning完整指南:7.2GB模型开机自启+日志监控配置
  • intv_ai_mk11快速部署教程:30秒获取GPU服务地址,5分钟完成首次高质量对话
  • MedGemma作品集:AI解读医学影像的精彩案例与效果展示
  • 用MATLAB和RSOME搞定报童问题:一个数据驱动的库存优化实战教程
  • TouchGAL终极指南:如何免费搭建一站式Galgame纯净社区