在 Hive 中分区和桶化表的区别是什么?

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

188326 次浏览

分区 数据通常用于水平分配负载,这有利于性能,并有助于以逻辑方式组织数据。例子: 如果我们正在处理一个大的 employee表,并且经常使用 WHERE子句运行查询,这些子句将结果限制在特定的国家或部门。为了获得更快的查询响应,Hive 表可以是 PARTITIONED BY (country STRING, DEPT STRING)。分区表改变了 Hive 的数据存储结构,现在 Hive 将创建反映分区结构的子目录,如

.../雇员/国家 = ABC/DEPT = XYZ

如果从 country=ABC查询员工限制,它将只扫描一个目录 country=ABC的内容。这可以显著提高查询性能,但前提是分区方案反映了公共过滤。分区特性在 Hive 中非常有用,但是,创建太多分区的设计可能会优化某些查询,但对其他重要查询是有害的。另一个缺点是有太多的分区是大量的 Hadoop 文件和目录被不必要的创建和 NameNode 的开销,因为它必须将文件系统的所有元数据保存在内存中。

Bucting 是另一种将数据集分解为更易于管理的部分的技术。例如,假设一个表使用 date作为顶级分区,使用 employee_id作为第二级分区,这会导致太多的小分区。相反,如果我们桶的雇员表和使用 employee_id作为桶的列,该列的值将被散列一个用户定义的数字到桶。具有相同 employee_id的记录将始终存储在相同的存储桶中。假设 employee_id的数量远大于桶的数量,那么每个桶将有许多 employee_id。在创建表时,您可以像 CLUSTERED BY (employee_id) INTO XX BUCKETS;那样指定其中 XX 是桶的数量。桶装有几个好处。桶的数量是固定的,因此它不会随着数据而波动。如果有两个表受到 employee_id的挑战,Hive 可以创建逻辑正确的抽样。桶也有助于做有效的地图边连接等。

我想我回答这个问题有点晚了,但它一直出现在我的视频中。

Navneet 提供了很好的答案。

分区有助于消除数据(如果在 WHERE 子句中使用的话) ,而存储区有助于将每个分区中的数据组织成多个文件,因此相同的数据集总是写在同一个存储区中。对柱子的连接有很大帮助。

假设有一个包含五列的表,name、 server _ date、 some _ col3、 some _ col4和 some _ col5。假设您已经在 Server _ date上对表进行了分区,并在 姓名列上进行了10次桶分区,那么您的文件结构如下所示。

  1. Server _ date = xyz
    • 00000 _ 0
    • 00001 _ 0
    • 00002 _ 0
    • ........
    • 00010 _ 0

这里的 Server _ date = xyz是分区,000文件是每个分区中的存储桶。存储桶是基于一些散列函数计算的,因此具有 Name = Sandy的行总是放在同一个存储桶中。

蜂群分区:

分区根据表列的值将大量数据划分为多个切片。

假设您存储的是遍布全球196多个国家、跨越约50亿亿条目的人员信息。如果你想查询某个特定国家(梵蒂冈城)的人,在没有分区的情况下,你必须扫描所有50亿卢比的条目,甚至可以获取一个国家的数千条目。如果根据国家对表进行分区,只需检查一个国家分区的数据,就可以对查询过程进行微调。蜂巢分区为列值创建一个单独的目录。

优点:

  1. 水平分布执行负载
  2. 在数据量较小的分区情况下,更快地执行查询。例如,从“ 梵蒂冈城”中得到的人口返回非常快,而不是搜索全世界的人口。

缺点:

  1. 创建太多小分区的可能性——太多目录。
  2. 对于给定分区的低容量数据有效。但是有些查询,比如对大量数据进行逐组查询,仍然需要很长时间才能执行。例如,中国的人口组合与梵蒂冈城的人口组合相比需要很长时间。如果数据偏向于某个特定的分区值,那么分区并不能解决响应性问题。

蜂巢漏斗:

Bucting 将数据分解为更易于管理或相等的部分。

使用分区,您可以根据列值创建多个小分区。如果要存储存储桶,则需要限制存储数据的存储桶的数量。这个数字是在表创建脚本期间定义的。

优点

  1. 由于每个分区中的数据量相同,在 Map 端的连接将更快。
  2. 更快的查询响应,比如分区

缺点

  1. 您可以在创建表的过程中定义存储桶的数量,但是必须由程序员手动加载等量的数据。

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

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

然后 hive 将在目录层次结构中存储数据,如

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

因此,在进行分区时必须非常小心,因为如果您使用 employee _ id 进行实例分区,并且拥有数百万名员工,那么您的文件系统中最终将拥有数百万个目录。 术语“ 枢机主教”是指字段可能具有的值的数目。例如,如果您有一个“ country”字段,那么世界上的国家大约是300个,因此基数大约是300个。对于类似于每毫秒更改一次的‘ time戳 _ ms’字段,基数可以是数十亿。一般来说,当选择一个字段进行分区时,它不应该具有很高的基数,因为这样会导致文件系统中有太多的目录。

另一方面,聚类又名桶,将产生固定数量的文件,因为您确实指定了桶的数量。Hive 将要做的就是获取字段,计算一个散列,并为这个桶分配一个记录。 但是,如果使用256个 bucket,并且所在字段的基数较低(例如,它是美国的一个州,因此只能有50个不同的值) ,会发生什么情况呢?您将有50个带有数据的存储桶和206个没有数据的存储桶。

有人已经提到分区可以显著减少查询的数据量。所以在我的示例表中,如果您只想从某个日期开始查询,那么按年/月/天进行分区将大大减少 IO 的数量。 我想有人也提到了 bucket 如何加速与其他表 有完全相同的桶的连接,所以在我的例子中,如果你在同一个 employee _ id 上连接两个表,hive 可以一桶一桶地连接(如果它们已经根据 employee _ id 排序,那就更好了,因为它将合并已经排序的部分,这在线性时间即 O (n)中工作)。

因此,当场具有较高的基数且数据在桶中均匀分布时,桶法工作良好。当分区字段的基数不太高时,分区工作得最好。

此外,您可以在多个字段上进行分区有一个订单(年/月/天是一个很好的例子) ,而 你只能在一块场地上投球

不同之处在于 水桶按列名划分文件,而 分区按表中的特定值划分下面的文件

希望我的定义是正确的

在进入 Bucketing之前,我们需要了解什么是 Partitioning。让我们以下表为例。请注意,在下面的例子中,我只提供了12条记录,用于初学者级别的理解。在实时场景中,您可能拥有数百万条记录。

enter image description here



分区
————————-
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的开销。



水桶
——————
Bucketing用于克服我在分区部分中提到的 cons。如果列中的重复值非常少(示例-主键列) ,则应使用此方法。这类似于 RDBMS 中主键列上的索引的概念。在我们的表中,我们可以采用 Sales_Id列进行冲压。当我们需要查询 sales_id列时,它将非常有用。

下面是 bucket 的语法。

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

在这里,我们将进一步将数据分割成更多的分区上的文件。

enter image description here

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

这里有很多很棒的回答,我想简短的记住分区和桶之间的区别。

您通常在不太唯一的列上进行分区。

例如,如果考虑使用国家、人名和他们的生物特征 ID 作为示例的世界人口。正如你所猜测的那样,乡村地区将是最不独特的栏目,而生物识别 ID 将是最独特的栏目。因此,理想情况下,您需要按国家对表进行分区,并使用生物度量 ID 将其装入桶中。

基于以下原因,强烈建议在 Hive 表中使用 Partitions-

  • 插入到 Hive 表应该更快(因为它使用多个线程 将数据写入分区)
  • 来自 Hive 表的查询应该是高效且低延迟的。

例子:-

假设 Input File (100GB)加载到 temp-hive-table 中,并且它包含来自不同地理位置的银行数据。

没有分区的蜂箱表

Insert into Hive table Select * from temp-hive-table


/hive-table-path/part-00000-1  (part size ~ hdfs block size)
/hive-table-path/part-00000-2
....
/hive-table-path/part-00000-n

这种方法的问题是-它将扫描整个数据为任何查询您运行在这个表。与其他使用分区和 Bucting 的方法相比,响应时间会更长。

带分区的蜂窝表

Insert into Hive table partition(country) Select * from temp-hive-table


/hive-table-path/country=US/part-00000-1       (file size ~ 10 GB)
/hive-table-path/country=Canada/part-00000-2   (file size ~ 20 GB)
....
/hive-table-path/country=UK/part-00000-n       (file size ~ 5 GB)

优点——在为特定地理事务查询数据时,可以更快地访问数据。 缺点-插入/查询数据可以通过在每个分区内拆分数据来进一步改进。

带分区和桶装的蜂窝表

注意: 使用“ CLUSTERED BY (Partiton _ Column)分为5个桶来创建蜂巢表

Insert into Hive table partition(country) Select * from temp-hive-table


/hive-table-path/country=US/part-00000-1       (file size ~ 2 GB)
/hive-table-path/country=US/part-00000-2       (file size ~ 2 GB)
/hive-table-path/country=US/part-00000-3       (file size ~ 2 GB)
/hive-table-path/country=US/part-00000-4       (file size ~ 2 GB)
/hive-table-path/country=US/part-00000-5       (file size ~ 2 GB)


/hive-table-path/country=Canada/part-00000-1   (file size ~ 4 GB)
/hive-table-path/country=Canada/part-00000-2   (file size ~ 4 GB)
/hive-table-path/country=Canada/part-00000-3   (file size ~ 4 GB)
/hive-table-path/country=Canada/part-00000-4   (file size ~ 4 GB)
/hive-table-path/country=Canada/part-00000-5   (file size ~ 4 GB)


....
/hive-table-path/country=UK/part-00000-1       (file size ~ 1 GB)
/hive-table-path/country=UK/part-00000-2       (file size ~ 1 GB)
/hive-table-path/country=UK/part-00000-3       (file size ~ 1 GB)
/hive-table-path/country=UK/part-00000-4       (file size ~ 1 GB)
/hive-table-path/country=UK/part-00000-5       (file size ~ 1 GB)

优点-更快的插入。更快的查询。

缺点-桶将创建更多的文件。在某些特定的情况下,可能会有许多小文件的问题

希望这个能帮上忙! !