繁体   English   中英

在Hive中分区和分区表有什么区别?

[英]What is the difference between partitioning and bucketing a table in Hive ?

我知道两者都是在表中的列上执行但是每个操作的不同之处。

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

... / employees / country = ABC / DEPT = XYZ

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

Bucketing是另一种将数据集分解为更易于管理的部分的技术。 例如,假设一个表使用date作为顶级分区而employee_id作为二级分区导致太多小分区。 相反,如果我们对employee表进行存储并使用employee_id作为bucketing列,则此列的值将由用户定义的数字散列到存储桶中。 具有相同employee_id记录将始终存储在同一个存储桶中。 假设employee_id的数量远远大于桶的数量,则每个桶将具有许多employee_id 创建表时,您可以指定CLUSTERED BY (employee_id) INTO XX BUCKETS; 其中XX是桶的数量。 Bucketing有几个优点。 存储桶的数量是固定的,因此不会随数据而波动。 如果employee_id两个表进行了分块,则Hive可以创建逻辑上正确的抽样。 Bucketing还有助于进行有效的地图侧连接等。

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

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进行分区并且您拥有数百万名员工,那么您的文件系统中最终将拥有数百万个目录。 术语“ 基数 ”是指字段可能具有的可能值的数量。 例如,如果您有一个“国家/地区”字段,那么世界上的国家/地区大约为300,因此基数为300。 对于像'timestamp_ms'这样每毫秒变化的字段,基数可能是数十亿。 通常,在选择用于分区的字段时,它不应该具有高基数,因为在文件系统中最终会有太多目录。

另一方面,群集aka bucketing将产生固定数量的文件,因为您确实指定了桶的数量。 什么配置单元将采取该字段,计算哈希值并将记录分配给该存储桶。 但是如果你使用让我们说256个桶并且你正在推销的字段具有低基数(例如,它是美国州,那么只能有50个不同的值)会发生什么? 你将有50个数据桶和206个没有数据的存储桶。

有人已经提到过分区如何大大减少您查询的数据量。 因此,在我的示例表中,如果您只想从特定日期向前查询,按年/月/日划分将大大减少IO的数量。 我认为有人还提到了bucketing如何加速与具有完全相同的bucketing的其他表的连接,所以在我的例子中,如果你在同一个employee_id上​​加入两个表,hive可以逐桶加入(甚至更好)如果它们已经按employee_id排序,因为它将合并已经排序的部分,这在线性时间即O(n)中有效。

因此,当字段具有高基数并且数据在桶之间均匀分布时,分段效果很好。 当分区字段的基数不太高时,分区效果最佳。

此外, 您可以使用订单(年/月/日是一个很好的示例) 对多个字段进行分区 ,而您只能在一个字段上 进行分区

我想我迟到了回答这个问题,但它一直在我的饲料中出现。

Navneet提供了出色的答案。 直观地添加它。

分区有助于消除数据(如果在WHERE子句中使用),其中bucketing有助于将每个分区中的数据组织成多个文件,因此同一组数据始终写在同一个存储桶中。 在列的加入方面有很多帮助。

假设您有一个包含五列的表,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文件是每个分区中的桶。 存储桶是根据一些散列函数计算的,因此名称为Sandy的行将始终位于同一个存储桶中。

Hive分区:

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

假设您存储的信息遍布全球196个国家/地区,覆盖了大约500亿条记录。 如果你想查询来自特定国家(梵蒂冈城)的人,在没有分区的情况下,你必须扫描所有500亿条的条目,甚至可以获取一个国家的一千个条目。 如果您根据国家/地区对表进行分区,则只需检查一个国家/地区分区的数据即可微调查询过程。 Hive分区为列值创建单独的目录。

优点:

  1. 水平分配执行负载
  2. 在具有低数据量的分区的情况下更快地执行查询。 例如,让“ 梵蒂冈城 ”的人口回归非常快,而不是搜索整个世界的人口。

缺点:

  1. 太多小分区创建的可能性 - 目录太多。
  2. 对给定分区的低容量数据有效。 但是一些像大量数据分组的查询仍需要很长时间才能执行。 例如,与梵蒂冈城的人口分组相比,中国的人口分组需要很长时间。 在数据偏向特定分区值的情况下,分区不解决响应性问题。

Hive Bucketing:

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

通过分区,您可以根据列值创建多个小分区。 如果您要进行分组,则限制存储数据的桶数。 此数字在表创建脚本中定义。

优点

  1. 由于每个分区中的数据量相等,因此Map侧的连接速度会更快。
  2. 更快的查询响应,如分区

缺点

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

区别在于bucketing按列名划分文件,而分区将文件划分为表中的特定值

希望我正确定义它

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

在此输入图像描述



PARTITIONING
---------------------
Partitioning用于在查询数据时获得性能。 例如,在上表中,如果我们编写下面的sql,它需要扫描表中的所有记录,这会降低性能并增加开销。

select * from sales_table where product_id='P1'

为了避免全表扫描并且只读取与product_id='P1'相关的记录,我们可以根据product_id列将(将hive表的文件拆分)分成多个文件。 通过这个,hive表的文件将被分成两个文件,一个是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 当我们需要查询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桶,因此每个product_id分为3个文件。 它在内部使用modulo operator来确定每个sales_id应该存储在哪个桶中。 例如,对于product_id='P1'sales_id=1将存储在000001_0文件中(即1%3 = 1), sales_id=2将存储在000002_0文件中(即2%3 = 2), sales_id=3将存储在000000_0文件中(即3%3 = 0)等。

这里有很好的回应。 我想简短地记住分区和桶之间的区别。

您通常在不太独特的列上进行分区。 并且在最独特的专栏上进行推销。

例如,如果您将具有国家/地区,人名及其生物指标ID的世界人口视为示例。 您可以猜测,国家/地区字段将是不太独特的列,生物指标ID将是最独特的列。 因此,理想情况下,您需要按国家/地区对表进行分区,并按生物指标ID对其进行分析。

由于以下原因,强烈建议在Hive表中使用分区 -

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

示例: -

假设输入文件(100 GB)被加载到temp-hive-table中,它包含来自不同地理位置的银行数据。

没有分区的Hive表

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

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

带分区的Hive表

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)

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

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

希望这会有所帮助!!

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM