hadoop学习---Hive分桶表的机制及其查询优化方案

ops/2024/9/23 11:20:56/

什么是分桶表?

分桶是将数据集分解成更容易管理的若干部分的一个技术,是比分区更为细粒度的数据范围划分。

主要是用于分文件的,在建表的时候,指定按照那些字段执行分桶操作,并可以设置需要分多少个桶,当插入数据的时候,执行MR的分区的操作,将数据分散各个分区(hive分桶)中,默认分发方案: hash 取模

 如何构建一个分桶表呢?

sql">create table test_buck(id int,name string)
clustered by(id) sorted by (id asc) into 6 buckets --创建分桶表的sql
row format delimited fields terminated by '\t';

CLUSTERED BY来指定划分桶所用列

SORTED BY对桶中的一个或多个列进行排序

into 6 buckets指定划分桶的个数

如何向分桶表添加数据呢?

标准格式:
1)创建一张与分桶表一样的临时表,唯一区别这个表不是一个分桶表

2)将数据加载到这个临时表中
3)通过 insert into + select语句将数据导入到分桶表中
说明: sqoop不支持直接对分桶表导入数据

分桶是如何提高效率的?

分区数量过于庞大以至于可能导致文件系统崩溃时,或数据集找不到合理的分区字段时,我们就需要使用分桶来解决问题了。

分区中的数据可以被进一步拆分成桶,不同于分区对列直接进行拆分,桶往往使用列的哈希值对数据打散,并分发到各个不同的桶中从而完成数据的分桶过程。

注意,hive使用对分桶所用的值进行hash,并用hash结果除以桶的个数做取余运算的方式来分桶,保证了每个桶中都有数据,但每个桶中的数据条数不一定相等

如果另外一个表也按照同样的规则分成了一个个小文件。两个表join的时候,就不必要扫描整个表,只需要匹配相同分桶的数据即可,从而提升效率

在数据量足够大的情况下,分桶比分区有更高的查询效率。

分桶和分区的区别:

  1. 分桶对数据的处理比分区更加细粒度化:分区针对的是数据的存储路径;分桶针对的是数据文件
  2. 分桶是按照列的哈希函数进行分割的,相对比较平均;而分区是按照列的值来进行分割的,容易造成数据倾斜;
  3. 分桶和分区两者不干扰,可以把分区表进一步分桶。

分桶表有什么作用呢?

1.进行数据采样

在真实的大数据分析过程中,由于数据量较大,开发和自测的过程比较慢,严重影响系统的开发进度。此时就可以使用分桶来进行数据采样。采样使用的是一个具有代表性的查询结果而不是全部结果,通过对采样数据的分析,来达到快速开发和自测的目的,节省大量的研发成本。

2.提升查询的效率(单表|多表)

单表查询时,基于hash值进行分桶的机制下查询时可直接锁定对应桶,不需要全局扫描,节省查询时间,提高效率。

如何进行数据采样?

采样函数:tablesample(bucket x out of y on column) ;

sql">select * from table tablesample(bucket x out of y on column)

 放置位置:紧紧跟在from后面,如果表有别名,放在别名前面。

说明:
            x:  从第几个桶开始进行采样
            y:  抽样比例(总桶数/y=分多少个桶)
            column: 分桶的字段, 可以省略的

注意:
           x 不能大于 y
           y 必须是表的分桶数量的倍数或者因子

案例
            1) 假设 A表有10个桶,  请分析, 下面的采样函数, 会将那些桶抽取出来
                 tablesample(bucket 2 out of 5 on xxx)会抽取几个桶呢?

                   总桶 / y =  分桶数量    2
                   抽取第几个编号的桶?  (x+y)
                   2,7
            2)  假设 A表有20个桶,  请分析, 下面的采样函数, 会将那些桶抽取出来
                    tablesample(bucket 4 out of 4 on xxx)会抽取几个桶呢?  

                 总桶 / y =  分桶数量    5
                 抽取第几个编号的桶?  (x+y)
                   4,8,12,16,20

如何提升查询的效率?(多表查询)

思考: 当多表进行join的时候, 如何提升join效率呢?

 小表和大表:

在进行join的时候, 将小表的数据放置到每一个读取大表的mapTask的内存中, 让mapTask每读取一次大表的数据都和内存中小表的数据进行join操作, 将join上的结果输出到reduce端即可, 从而实现在map端完成join的操作

如何开启map Join?
    set hive.auto.convert.join=true;  -- 是否开启map Join
    set hive.auto.convert.join.noconditionaltask.size=512000000; -- 设置小表最大的阈值(设置block cache 缓存大小)
    
map Join  不限制任何表 

为什么不采用reduce join呢?

1) 可能出现数据倾斜的问题
2) 导致reduce压力较大

中型表和大表:

中型表: 与小表相比 大约是小表3~10倍左右

解决方案:
1.能提前过滤就提前过滤掉(一旦提前过滤后,会导致中型表的数据量会下降,有可能达到小表阈值)
2.如果join的字段值有大量的null,可以尝试添加随机数(保证各个reduce接收数据量差不多的,减少数据倾斜问题)

3.基于分桶表的: bucket map join

bucket map join条件

1) set hive.optimize.bucketmapjoin = true;
2) 一个表的bucket数是另一个表bucket数的整数倍
3) bucket列 == join列
4) 必须是应用在map join的场景中

注意:如果表不是bucket的,则只是做普通join

在这种机制下减少中型表的数据量,将对应的join条件的数据放到内存中进行关联,map join还是在内存中进行,只不过对应的数据量减少了。

大表和大表:

解决方案:

1. 能提前过滤就提前过滤掉(减少join之间的数量, 提升reduce执行效率)。
2. 如果join的字段值有大量的null, 可以尝试添加随机数(保证各个reduce接收数据量差不多的, 减少数据倾斜问题)。

3. SMB Map join (sort merge bucket map join)

sort merge bucket map join 

实现SMB map join的条件要求: 
1) 一个表的bucket数等于另一个表bucket数(分桶数量是一致)
2) bucket列 == join列 == sort 列
3) 必须是应用在bucket map join的场景中
4)   开启相关的参数:
    -- 开启SMB map join
    set hive.auto.convert.sortmerge.join=true;
    set hive.auto.convert.sortmerge.join.noconditionaltask=true;
    --写入数据强制排序
    set hive.enforce.sorting=true;
    set hive.optimize.bucketmapjoin.sortedmerge = true; -- 开启自动尝试SMB连接


http://www.ppmy.cn/ops/33953.html

相关文章

【QEMU系统分析之实例篇(十五)】

系列文章目录 第十五章 QEMU系统仿真的机器创建分析实例 文章目录 系列文章目录第十五章 QEMU系统仿真的机器创建分析实例 前言一、QEMU是什么?二、QEMU系统仿真的机器创建分析实例1.系统仿真的命令行参数2.应用旧的机器设置项qemu_apply_legacy_machine_options()…

探索CSS3文本效果:打造魅力无限的网页排版

CSS3为网页设计带来了革命性的变化,特别是在文本效果方面,它赋予了开发者前所未有的创意空间。本文将带你深入了解CSS3中一些令人兴奋的文本效果,从基本的阴影处理到复杂的动画效果,每个技巧都将通过实际代码示例展现其魅力所在。…

二进制方式安装mysql

一、创建mysql目录 mkdir /mytools cd /mytools 二、下载mysql二进制 wget https://downloads.mysql.com/archives/get/p/23/file/mysql-5.7.30-linux-glibc2.12-x86_64.tar.gz 三、解压缩二进制mysql代码 tar -zxvf mysql-5.7.30-linux-glibc2.12-x86_64.tar.gz 四、配置…

【刷题(2)】矩阵

一、矩阵问题基础 遍历: for i in range(len(matrix[0])): for j in range(len(matrix): while 倒序遍历: for i in range(right,left,-1) 临时存储:temp w,h:len(matrix[0])-1 len(matrix)-1 left,right,top,bottom:0 len(matrix[0])-1 0 l…

匹配网络(Matching Networks)和原型网络(Prototypical Networks):区别详解

匹配网络(Matching Networks)和原型网络(Prototypical Networks) 匹配网络与原型网络:区别详解匹配网络(Matching Networks)核心特点:应用场景: 原型网络(Pro…

vue Props

Props 声明​ 一个组件需要显式声明它所接受的 props&#xff0c;这样 Vue 才能知道外部传入的哪些是 props&#xff0c;哪些是透传 attribute 在使用 <script setup> 的单文件组件中&#xff0c;props 可以使用 defineProps() 宏来声明&#xff1a; <script setup…

每日一题3:Pandas数据获取

一、每日一题 编写一个解决方案&#xff0c;选择 student_id 101 的学生的 name 和 age 并输出。 解答&#xff1a; import pandas as pddef selectData(students: pd.DataFrame) -> pd.DataFrame:return students.loc[students["student_id"] 101, ["nam…

JVM组成之类加载器

类加载器&#xff08;ClassLoader&#xff09;&#xff1a;是Java虚拟机提供给应用程序去实现获取类和接口字节码数据的技术。 类加载器多数是有Java编写的&#xff0c;也有部分是c编写的&#xff0c;负责接收来自外部的二进制数据&#xff0c;然后执行JNI&#xff08;也就是本…