我知道两者都是在表格的列上执行的,但每个操作的不同之处。
答案 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 列上进行了分区,您的文件结构将如下所示。
此处 server_date = xyz 是分区, 000 文件是每个分区中的存储桶。存储桶是根据某些散列函数计算的,因此 name = Sandy 的行将始终位于同一个存储桶中。
答案 3 :(得分:14)
Hive分区:
分区根据表列的值将大量数据划分为多个切片。
假设您存储的信息遍布全球196个国家/地区,覆盖约500亿条记录。如果你想查询来自特定国家(梵蒂冈城)的人,在没有分区的情况下,你必须扫描所有500亿条的条目,甚至可以获取一个国家的一千个条目。如果您根据国家/地区对表进行分区,则只需检查一个国家/地区分区的数据即可微调查询过程。 Hive分区为列值创建单独的目录。
<强> 优点: 强>
<强> 缺点: 强>
Hive Bucketing:
Bucketing将数据分解为更易于管理或相同的部分。
通过分区,您可以根据列值创建多个小分区。如果您要进行分组,则限制存储数据的桶数。此数字是在表创建脚本中定义的。
<强> 赞成 强>
<强> 缺点 强>
答案 4 :(得分:6)
区别在于分组按列名划分文件,分区将文件划分为表格中的特定值
希望我正确定义了
答案 5 :(得分:2)
在进入Bucketing
之前,我们需要了解Partitioning
是什么。让我们以下表为例。请注意,在下面的示例中,我仅给出了12条记录以供初学者理解。在实时方案中,您可能有数百万条记录。
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
在这里,我们将进一步在分区顶部将数据拆分为几个文件。
由于我们指定了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表中使用分区-
示例:-
假定输入文件(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)
优点-更快插入。快速查询。
缺点-存储桶将创建更多文件。在某些特定情况下,许多小文件可能会出现问题
希望这会有所帮助!