Hive之分区(Partitions)和桶(Buckets)

2024-01-20 19:08
文章标签 分区 hive partitions buckets

本文主要是介绍Hive之分区(Partitions)和桶(Buckets),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

hive引入partition和bucket的概念,中文翻译分别为分区和桶(我觉的不是很合适,但是网上基本都是这么翻译,暂时用这个吧),这两个概念都是把数据划分成块,分区是粗粒度的划分桶是细粒度的划分,这样做为了可以让查询发生在小范围的数据上以提高效率。

首先介绍分区的概念,还是先来个例子看下如果创建分区表:
[code lang=”sql”]
create table logs_partition(ts bigint,line string) –ts timestamp line 每一行日志
partitioned by (dt string,country string) — 分区列 dt 日志产生日期
[/code]
创建分区表需要在定义表的时候声明分区列,这个分区列是个比较有意思的东西下面来看看,向表中导入数据:
[code lang=”sql”]
load data local inpath ‘input/hive/partitions/file1′
into table logs_partition
partition(dt=’2001-01-01′,country=’GB’);
…….
— 看下表的结构
hive> desc logs_partition;
OK
ts bigint None
line string None
dt string None
country string None

# Partition Information
# col_name data_type comment

dt string None
country string None
Time taken: 0.265 seconds, Fetched: 10 row(s)

查看一个表的所有分区
hive> show partitions logs_partition;
OK
dt=2001-01-01/country=GB
dt=2001-01-01/country=US
dt=2001-01-02/country=GB
dt=2001-01-02/country=US
Time taken: 0.186 seconds, Fetched: 4 row(s)

[/code]
导入完数据后看下hive数据仓库表logs_partition下的文件目录结构
/user/hive/warehouse/logs_partition
Screenshot from 2013-10-10 17:46:25
看到了吧分区列都成了目录了,这样查询的时候就会定位到某个目录下而大大提高了查询效率,在查看表结构的时候分区列跟其他列并无区别,看个查询语句:
[code lang=”sql”]
SELECT ts, dt, line
FROM logs
WHERE country=’GB’;

1 2001-01-01 Log line 1
2 2001-01-01 Log line 2
4 2001-01-02 Log line 4
Time taken: 36.316 seconds, Fetched: 3 row(s)

[/code]
这个查询只会查询file1, file2, file4这三个文件还有一个有趣的问题就是,查看下数据文件fieldX
里面都只包含两列ts和line并不包含dt和country这两个分区列,但是从查询结果看分区列和非分区列并无差别,实际上分区列都是从数据仓库的分区目录名得来的。

接下来说说桶,桶是更为细粒度的数据范围划分,它能使一些特定的查询效率更高,比如对于具有相同的桶划分并且jion的列刚好就是在桶里的连接查询,还有就是示例数据,对于一个庞大的数据集我们经常需要拿出来一小部分作为样例,然后在样例上验证我们的查询,优化我们的程序。

下面看看如何创建带桶的表
[code lang=”sql”]
create table bucket_user (id int,name string)
clustered by (id) into 4 buckets;
[/code]
关键字clustered声明划分桶的列和桶的个数,这里以用户的id来划分桶,划分4个桶。
以下为了简便划分桶的列简称为桶列
hive会计算桶列的hash值再以桶的个数取模来计算某条记录属于那个桶

向这种带桶的表里面导入数据有两种方式,一种是外部生成的数据导入到桶表,一种是利用hive来帮助你生成桶表数据
由于hive在load数据的时候不能检查数据文件的格式与桶的定义是否匹配,如果不匹配在查询的时候就会报错,所以最好还是让hive来帮你生成数据,简单来说就是利用现有的表的数据导入到新定义的带有桶的表中,下面来看看:
已经存在的表:
[code lang=”bash”]
hive> select * from users;
OK
0 Nat
2 Joe
3 Kay
4 Ann

hive> set hive.enforce.bucketing=true –必须设置这个数据,hive才会按照你设置的桶的个数去生成数据
[/code]

下面把user的数据导入到bucketed_users中
[code language=”lang='sql”]
insert overwrite table bucketed-users
select * from users;
[/code]
然后见证奇迹的时刻:
[code lang=”bash”]
hive> dfs -ls /user/hive/warehouse/bucketed_users;
-rw-r–r– 1 root supergroup 12 2013-10-10 18:48 /user/hive/warehouse/bucketed_users/000000_0
-rw-r–r– 1 root supergroup 0 2013-10-10 18:48 /user/hive/warehouse/bucketed_users/000001_0
-rw-r–r– 1 root supergroup 6 2013-10-10 18:48 /user/hive/warehouse/bucketed_users/000002_0
-rw-r–r– 1 root supergroup 6 2013-10-10 18:48 /user/hive/warehouse/bucketed_users/000003_0

hive> dfs -cat /user/hive/warehouse/bucketed_users/000000_0;
0Nat
4Ann

[/code]

下面来看看利用bucket来对示例数据进行查询
[code lang=”sql”]
—带桶的表
select * from bucketed_users
tablesample(bucket 1 out of 4 on id);

—不带桶的表
select * from users
tablesample(bucket 1 out of 4 on rand());

[/code]
tablesample的作用就是让查询发生在一部分桶上而不是整个数据集上,上面就是查询4个桶里面第一个桶的数据
相对与不带桶的表这无疑是效率很高的,因为同样都是需要一小部分数据,但是不带桶的表需要使用rand()函数,需要在整个数据集上检索。

出处:http://www.aahyhaa.com/archives/316

hive中table可以拆分成partition,table和partition可以通过‘CLUSTERED BY ’进一步分bucket,bucket中的数据可以通过‘SORT BY’排序。
bucket主要作用:
1. 数据sampling
2. 提升某些查询操作效率,例如mapside join
需要特别注意的是:clustered by和sorted by不会影响数据的导入,这意味着,用户必须自己负责数据如何如何导入,包括数据的分桶和排序。

tablesample是抽样语句,语法:TABLESAMPLE(BUCKET x OUT OF y)

y必须是table总bucket数的倍数或者因子。hive根据y的大小,决定抽样的比例。例如,table总共分了64份,当y=32时,抽取(64/32=)2个bucket的数据,当y=128时,抽取(64/128=)1/2个bucket的数据。x表示从哪个bucket开始抽取。例如,table总bucket数为32,tablesample(bucket 3 out of 16),表示总共抽取(32/16=)2个bucket的数据,分别为第3个bucket和第(3+16=)19个bucket的数据。


这篇关于Hive之分区(Partitions)和桶(Buckets)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/627026

相关文章

Hive和Hbase的区别

Hive 和 HBase 都是 Hadoop 生态系统中的重要组件,它们都能处理大规模数据,但各自有不同的适用场景和设计理念。以下是两者的主要区别: 1. 数据模型 Hive:Hive 类似于传统的关系型数据库 (RDBMS),以表格形式存储数据。它使用 SQL-like 语言 HiveQL 来查询和处理数据,数据通常是结构化或半结构化的。HBase:HBase 是一个 NoSQL 数据库,基

掌握Hive函数[2]:从基础到高级应用

目录 高级聚合函数 多进一出 1. 普通聚合 count/sum... 2. collect_list 收集并形成list集合,结果不去重 3. collect_set 收集并形成set集合,结果去重  案例演示 1. 每个月的入职人数以及姓名  炸裂函数  概述  案例演示 1. 数据准备 1)表结构 2)建表语句 3)装载语句 2. 需求 1)需求说明 2)答

数据库系统 第41节 数据库分区简介

数据库分区是一种数据库设计技术,用于将大型表或索引的数据分布到不同的物理区域,以提高查询性能、优化数据管理、简化维护任务,并提高数据的可用性。下面我将详细介绍每种分区类型,并结合伪代码或概念性的源代码来说明其实现方式。 1. 范围分区 (Range Partitioning) 范围分区是根据某个列的值范围来划分数据。例如,可以按照日期或数值范围来分区。 示例场景:一个订单表,按年份分区。

Windows环境下SD卡多分区 隐藏分区 解决python裸读写扇区失败

SD卡分区 右键“我的电脑”->“管理”->“磁盘管理”; 如果SD卡有文件系统,点击"删除卷",重新做卡; 删除文件系统后如下图,点击“新建简单卷”; 在导航页“指定卷大小”,设置分区的大小,留出剩余的空间; python读写SD卡 这里需要注意的是,写SD卡需要加锁,否则写不成功 #带文件系统,需要锁定卷,否则无法写扇区@contextlib.contextmanagerd

在不损坏数据的情况下给WIN7重新划分分区

小易接到个求助电话:我的机器上已经装好了系统,但是只有一个分区。我不想重装系统重新分区,能不能再分出一个分区?   这个故障可能是困惑很多网友的一个故障。一般,有一些第三方的软件可以实现这些功能。但是,现在在 Windows Vista/Windows 7 里允许你对现有分区大小进行一定范围的调整。   来看一下操作办法:   准备工作   这个操作必须要求你的文件系统是 N

如何调整c盘分区大小,怎样把c盘空间调整小些

新买的笔记本电脑回来后发现电脑只分了C盘和D盘两个区,C盘就占了很大的空间,如何调整c盘分区大小,这样可以多腾些空间出来利用呢?虽然Win7有磁盘管理器可以压缩分区实现把C盘调小些,但是它的功能有限,压缩后也是很大一部分空间在C盘浪费,那怎样把c盘空间调整小些呢,下载我们介绍一个工具来完成这些复杂的动作:   1、下载安装分区助手DiskTool中文版。   在主界面上你可以看到C盘有60

win10 gpt分区+uefi引导 卸载双系统ubuntu

1、首先暴力卸载ubuntu 在win10里面磁盘管理中找到对应的linux磁盘分区 删除卷OK 2、重启 出现下面(根据机型不同界面可能不一样 ) 3、exit 退出grub引导 进入uefi引导  选择win10引导项 (当然你要是一直按着进入bios boot的那个按键的话 也不用看第二步了 直接选择windows启动项进去 dell的话是F12) 4、进入

Kafka【十二】消费者拉取主题分区的分配策略

【1】消费者组、leader和follower 消费者想要拉取主题分区的数据,首先必须要加入到一个组中。 但是一个组中有多个消费者的话,那么每一个消费者该如何消费呢,是不是像图中一样的消费策略呢?如果是的话,那假设消费者组中只有2个消费者或有4个消费者,和分区的数量不匹配,怎么办? 所以这里,我们需要学习Kafka中基本的消费者组中的消费者和分区之间的分配规则: 同一个消费者组的消费者都订

【Hive Hbase】Hbase与Hive的区别与联系

问题导读: Hive与Hbase的底层存储是什么? hive是产生的原因是什么? habase是为了弥补hadoop的什么缺陷? 共同点: 1.hbase与hive都是架构在hadoop之上的。都是用hadoop作为底层存储 区别: 2.Hive是建立在Hadoop之上为了减少MapReduce jobs编写工作的批处理系统,HBase是为了支持弥补Hadoop对实时操作的缺陷的项目

【hive 日期转换】Hive中yyyymmdd和yyyy-mm-dd日期之间的切换

方法1: from_unixtime+ unix_timestamp--20171205转成2017-12-05 select from_unixtime(unix_timestamp('20171205','yyyymmdd'),'yyyy-mm-dd') from dual;--2017-12-05转成20171205select from_unixtime(unix_timestamp