在hive中对表进行分区和bucking有什么区别?

z9ju0rcb  于 2021-06-03  发布在  Hadoop
关注(0)|答案(8)|浏览(460)

我知道这两个操作都是在表中的一列上执行的,但是每个操作有何不同呢。

wwtsj6pe

wwtsj6pe1#

我想我回答这个问题已经晚了,但我的反馈中一直提到这个问题。
navneet提供了极好的答案。添加到它的视觉效果。
分区有助于消除数据,如果在where子句中使用,where-as-bucketing有助于将每个分区中的数据组织成多个文件,因此同一组数据总是写入同一个bucket。有助于很多列的连接。
假设您有一个包含五列的表:name、server\u date、some\u col3、some\u col4和some\u col5。假设您在server\ date上对表进行了分区,并在name列上添加了10个bucket,您的文件结构如下所示。
服务器\日期=xyz
00000_0
00001_0
00002_0
........
00010_0
这里server_date=xyz是分区,000个文件是每个分区中的存储桶。bucket是基于一些散列函数计算的,所以name=sandy的行总是放在同一个bucket中。

92vpleto

92vpleto2#

不同之处在于bucketing按列名划分文件,分区按表中的特定值划分下的文件
希望我的定义是正确的

jq6vz3qz

jq6vz3qz3#

配置单元分区:
分区根据表列的值将大量数据划分为多个片。
假设您存储的是分布在196多个国家的全世界人民的信息,这些国家大约有5亿条条目。如果你想查询来自某个国家(梵蒂冈城)的人,在没有分区的情况下,你必须扫描所有的50亿条条目,甚至要获取一个国家的数千条条目。如果您基于国家对表进行分区,您可以通过只检查一个国家分区的数据来微调查询过程。配置单元分区为列值创建单独的目录。
赞成的意见:
水平分布执行负载
在数据量较小的分区情况下执行查询的速度更快。e、 从“梵蒂冈城”得到的人口返回速度非常快,而不是搜索整个世界的人口。
欺骗:
小分区创建太多的可能性-目录太多。
对给定分区的低容量数据有效。但是,一些查询(如GROUPBY)在高数据量上仍然需要很长时间才能执行。e、 与梵蒂冈的人口分组相比,中国的人口分组需要很长时间。分区并不能解决数据向特定分区值倾斜时的响应问题。
Hive扣:
bucketing将数据分解为更易于管理或相等的部分。
通过分区,可以基于列值创建多个小分区。如果您选择bucketing,则会限制存储数据的bucket数。这个数字是在表创建脚本期间定义的。
赞成的意见
由于每个分区中的数据量相等,所以在Map端的连接将更快。
更快的查询响应(如分区)
欺骗
您可以在创建表的过程中定义存储桶的数量,但加载等量的数据必须由程序员手动完成。

yuvru6vn

yuvru6vn4#

前面的解释中缺少一些细节。为了更好地理解分区和bucketing是如何工作的,您应该了解数据是如何存储在hive中的。假设你有一张table

CREATE TABLE mytable ( 
         name string,
         city string,
         employee_id int ) 
PARTITIONED BY (year STRING, month STRING, day STRING) 
CLUSTERED BY (employee_id) INTO 256 BUCKETS

然后配置单元将数据存储在目录层次结构中,如

/user/hive/warehouse/mytable/y=2015/m=12/d=02

因此,在分区时必须小心,因为如果您例如按employee\u id进行分区,并且您有数百万个雇员,那么您的文件系统中最终会有数百万个目录。术语“基数”指的是字段可能具有的值的数目。例如,如果你有一个'country'字段,世界上的国家大约是300个,所以基数应该是~300。对于像“timestamp \u ms”这样每毫秒改变一次的字段,基数可以是数十亿。一般来说,当选择一个字段进行分区时,它不应该具有很高的基数,因为最终会导致文件系统中的目录太多。
另一方面,集群(也称为bucketing)将产生固定数量的文件,因为您确实指定了bucket的数量。hive将要做的是获取字段,计算一个哈希,并将一个记录分配给该bucket。但是,如果使用256个bucket,并且要bucketing的字段基数很低(例如,它是美国的一个州,所以只能有50个不同的值),会发生什么呢?您将有50个有数据的bucket,206个没有数据的bucket。
有人已经提到分区如何显著地减少您查询的数据量。所以在我的示例表中,如果您只想从某个日期开始查询,那么按年/月/日进行分区将显著减少io的数量。我认为有人还提到了bucketing如何加速与其他具有完全相同bucketing的表的联接,因此在我的示例中,如果要在同一个employee\u id上联接两个表,hive可以逐个bucket进行联接(如果它们已经按employee\u id排序,则效果更好,因为它将合并已排序的部分,在线性时间内工作(即o(n))。
因此,当字段具有较高的基数并且数据均匀分布在bucket之间时,bucketing工作得很好。当分区字段的基数不太高时,分区工作得最好。
此外,您可以使用订单(年/月/日是一个很好的例子)对多个字段进行分区,而您只能对一个字段进行bucket。

6qqygrtg

6qqygrtg5#

  • Partitioning 用于在查询数据时获得性能。例如,在上表中,如果我们编写下面的sql,它需要扫描表中的所有记录,这会降低性能并增加开销。
select * from sales_table where product_id='P1'

避免全表扫描,只读取与 product_id='P1' 我们可以基于 product_id 列。这样,配置单元表的文件将被拆分为两个文件,一个带有 product_id='P1' 其他的有 product_id='P2' . 现在,当我们执行上述查询时,它将只扫描 product_id='P1' 文件。

../hive/warehouse/sales_table/product_id=P1
../hive/warehouse/sales_table/product_id=P2

下面给出了创建分区的语法。注意,我们不应该使用 product_id 列定义以及以下语法中的非分区列。这应该只在 partitioned by 条款。

create table sales_table(sales_id int,trans_date date, amount int) 
partitioned by (product_id varchar(10))

缺点:分区时要非常小心。也就是说,它不应该用于重复值数量非常少的列(尤其是主键列),因为它增加了分区文件的数量并增加了系统的开销 Name node .
木扣

rqqzpn5f

rqqzpn5f6#

-------- Bucketing 是用来克服 cons 我在分区部分提到的。当列中的重复值很少(例如-主键列)时,应使用此选项。这类似于rdbms中主键列索引的概念。在我们的table上,我们可以 Sales_Id 扣件柱。当我们需要查询 sales_id 列。
下面是bucketing的语法。

create table sales_table(sales_id int,trans_date date, amount int) 
partitioned by (product_id varchar(10)) Clustered by(Sales_Id) into 3 buckets

在这里,我们将进一步将数据分割为分区之上的几个文件。

因为我们已经指定 3 bucket,它被分成3个文件 product_id . 它内部使用 modulo operator 以确定每个 sales_id 应该保存。例如,对于 product_id='P1' ,的 sales_id=1 将存储在000001\u 0文件中(即1%3=1), sales_id=2 将存储在000002\u 0文件中(即2%3=2), sales_id=3 将存储在0000000文件中(即3%3=0)等。

mxg2im7a

mxg2im7a7#

在进入 Bucketing ,我们需要明白什么 Partitioning 是。让我们以下表为例。请注意,在下面的示例中,我只给出了12条记录供初学者理解。在实时场景中,您可能有数百万条记录。

分区

bgibtngc

bgibtngc8#

分区数据通常用于水平分布负载,这有利于性能,并有助于以逻辑方式组织数据。例如:如果我们正在处理一个大的 employee 表并经常运行查询 WHERE 将结果限制在特定国家或部门的条款。为了更快的查询响应,可以使用配置单元表 PARTITIONED BY (country STRING, DEPT STRING) . 分区表改变了配置单元构造数据存储的方式,配置单元现在将创建反映分区结构的子目录,如
…/employees/country=/dept=xyz。
如果查询来自的员工限制 country=ABC ,它将只扫描一个目录的内容 country=ABC . 这可以极大地提高查询性能,但前提是分区方案反映公共过滤。分区特性在hive中非常有用,但是,创建太多分区的设计可能会优化某些查询,但对其他重要查询不利。另一个缺点是分区太多,即大量的hadoop文件和目录是不必要地创建的,而且namenode的开销很大,因为它必须在内存中保留文件系统的所有元数据。
bucketing是另一种将数据集分解为更易于管理的部分的技术。例如,假设一个表使用 date 作为顶层分区和 employee_id 因为第二级分区会导致太多的小分区。相反,如果我们将employee表 employee_id 作为bucketing列,此列的值将由用户定义的数字散列到bucket中。具有相同 employee_id 将始终存储在同一个桶中。假设 employee_id 比桶的数量大得多,每个桶都会有很多 employee_id . 在创建表时,您可以指定 CLUSTERED BY (employee_id) INTO XX BUCKETS; 其中xx是桶的数量。扣有几个优点。桶的数量是固定的,因此不会随数据波动。如果两张table被扣住 employee_id ,配置单元可以创建逻辑正确的采样。bucketing也有助于进行有效的Map边连接等。

相关问题