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

时间:2013-10-02 02:09:10

标签: hadoop hive

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

8 个答案:

答案 0 :(得分:229)

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

  

... /雇员/ 国= 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还有助于进行有效的地图侧连接等。

答案 1 :(得分:118)

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

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'这样每毫秒都会改变的字段,基数可能是数十亿。通常,在选择字段进行分区时,它不应该具有较高的基数,因为您最终会在文件系统中使用太多目录。

另一方面,群集也称为分段,将产生固定数量的文件,因为您确实指定了桶的数量。什么配置单元将采取该字段,计算哈希值并将记录分配给该存储桶。 但是,如果您使用let 256表示会发生什么情况,那么您所依赖的字段的基数较低(例如,它是美国的州,那么只能有50个不同的值)?您将拥有50个数据桶和206个没有数据的存储桶。

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

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

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

答案 2 :(得分:18)

我认为我在回答这个问题时已经迟到了,但它仍然在我的提要中出现。

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

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

假设您有一个包含五列的表,name,server_date,some_col3,some_col4和some_col5。假设您已经在 server_date 上对表进行了分区,并在10个存储桶中的 name 列上进行了分区,您的文件结构将如下所示。

  1. server_date = XYZ
    • 00000_0
    • 00001_0
    • 00002_0
    • ........
    • 00010_0
  2. 此处 server_date = xyz 是分区, 000 文件是每个分区中的存储桶。存储桶是根据某些散列函数计算的,因此 name = Sandy 的行将始终位于同一个存储桶中。

答案 3 :(得分:14)

Hive分区:

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

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

<强> 优点:

  1. 水平分配执行负载
  2. 在数据量较小的分区情况下,查询执行速度更快。例如从<#> 梵蒂冈城&#34;回报非常快,而不是搜索整个世界人口。
  3. <强> 缺点:

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

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

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

      <强> 赞成

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

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

答案 4 :(得分:6)

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

希望我正确定义了

答案 5 :(得分:2)

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

enter image description here



PARTITIONING
---------------------
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列时,它将很有用。

以下是存储分区的语法。

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个存储桶,因此每个product_id都会将其分为3个文件。它在内部使用modulo operator来确定每个sales_id应该存储在哪个存储桶中。例如,对于product_id='P1'sales_id=1将存储在 000001_0 文件(即1%3 = 1)中,sales_id=2将存储在< strong> 000002_0 文件(即2%3 = 2),sales_id=3将存储在 000000_0 文件(即3%3 = 0)等中。

答案 6 :(得分:0)

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

您通常在一个不太唯一的列上进行分区。并在最独特的列上进行分类。

例如,如果您考虑带有国家,人名及其生物特征ID的世界人口作为示例。您可能会猜到,“国家/地区”字段将是唯一性较差的列,而生物识别ID是唯一性最高的列。因此,理想情况下,您需要按国家/地区对表格进行分区,并按生物特征ID对其进行分类。

答案 7 :(得分:0)

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

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

示例:-

假定输入文件(100 GB)已加载到temp-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

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

带有分区的配置单元表

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个存储桶”创建配置单元表.... p

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)

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

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

希望这会有所帮助!