在Hive中对表进行分区和分区有什么区别?
我知道这两个表都在表中的一列进行,但每个操作又有什么不同。
分区数据通常用于水平分布负载,这具有性能优势,并有助于以合理的方式组织数据。 例如 :如果我们正在处理一个大的employee
表,并且经常使用WHERE
子句来运行查询,这些子句将结果限制在特定的国家或部门。 为了更快的查询响应,Hive表可以被PARTITIONED BY (country STRING, DEPT STRING)
。 分区表更改Hive如何构build数据存储,Hive现在将创build反映分区结构的子目录
… / employees / country = ABC / DEPT = XYZ 。
如果来自country=ABC
员工的查询限制,它将只扫描一个目录country=ABC
的内容。 这可以显着提高查询性能,但前提是分区scheme反映常见的过滤。 分区function在Hive中非常有用,但是,创build太多分区的devise可能会优化某些查询,但对其他重要查询不利。 其他缺点是具有太多的分区是由于必须将文件系统的所有元数据保留在内存中,所以大量的Hadoop文件和目录被不必要地创build并且向NameNode开销。
Bucketing是将数据集分解为更易于pipe理的部分的另一种技术。 例如,假设一个使用date
作为顶级分区, employee_id
作为第二级分区的表导致太多的小分区。 相反,如果我们存储员工表并使用employee_id
作为分组列,则此列的值将由用户定义的数字散列为存储桶。 具有相同employee_id
logging将始终存储在同一个存储桶中。 假设employee_id
的数量远远大于桶的数量,每个桶将有许多employee_id
。 在创build表的时候,你可以指定像CLUSTERED BY (employee_id) INTO XX BUCKETS;
其中XX是桶的数量。 Bucketing有几个优点。 桶的数量是固定的,所以它不会随着数据而波动。 如果两个表由employee_id
分区,Hive可以创build一个逻辑上正确的采样。 Bucketing还有助于实现高效的地图边连接等
从前面的解释中可以看出一些细节。 为了更好地理解分区和分区如何工作,您应该查看数据如何存储在configuration单元中。 假设你有一张桌子
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
那么configuration单元会将数据存储在目录层次结构中
/user/hive/warehouse/mytable/y=2015/m=12/d=02
所以,在分区时你必须小心,因为如果你通过employee_id进行实例分区,而且你拥有数以百万计的员工,那么最终你的文件系统中会有数以百万计的目录。 术语“ 基数 ”是指字段可能具有的可能值的数量。 例如,如果你有一个“国家”的领域,世界上的国家大约有300个,所以基数就是300个。 对于像“timestamp_ms”这样每毫秒发生一次更改的字段,基数可能是数十亿。 一般来说,在select一个分区字段时,它不应该有很高的基数,因为你的文件系统中的目录太多了。
另一方面,聚类又称分水器,将会产生固定数量的文件,因为你指定了水桶的数量。 什么configuration单元将做的是采取领域,计算一个哈希,并分配一个logging到该桶。 但是如果你使用256个桶并且你正在使用的字段有一个低基数(例如,它是一个美国状态,所以可能只有50个不同的值),会发生什么? 你将有50个数据桶和206个没有数据的桶。
有人已经提到分区如何能够大幅减less你正在查询的数据量。 因此,在我的示例表中,如果只想从某个特定的date向前查询,则按年/月/日进行分区将显着减lessIO的数量。 我认为有人还提到了bucketing如何加快与其他具有完全相同bucketing的表的连接,所以在我的示例中,如果您在同一个employee_id上join两个表,configuration单元可以逐个join连接(甚至更好如果它们已经按照employee_idsorting了,因为它将要在线性时间内运行的mergesort)。
所以,当字段高基数,数据在桶之间均匀分布时,分段运行良好。 当分区字段的基数不太高时,分区效果最好。
另外, 你可以在多个字段上进行分区 ,一个命令(年/月/日就是一个很好的例子),而你只能在一个字段上 进行分区 。
我想我在回答这个问题的时候已经晚了,但是它一直在我的饲料中出现。
Navneet提供了很好的答案。 直观地添加到它。
分区有助于消除数据,如果在WHERE子句中使用的话,分段有助于将每个分区中的数据组织成多个文件,因此同一组数据总是写入同一个分区。 有助于join专栏。
假设你有一个包含五列的表,name,server_date,some_col3,some_col4和some_col5。 假设你已经在server_date上对表进行了分区,并在10个桶中的名称列上进行了分区,那么你的文件结构将如下所示。
- server_date = XYZ
- 00000_0
- 00001_0
- 00002_0
- ……..
- 00010_0
这里server_date = xyz是分区, 000文件是每个分区的桶。 存储桶是根据一些散列函数计算的,所以名称= Sandy的行将总是在相同的存储桶中。
Hive分区:
分区根据表列的值将大量的数据分成多个片段。
假设您正在存储遍布世界各地的196个国家的人员信息,跨越500多个条目。 如果你想查询来自某个特定国家(梵蒂冈城)的人,在没有分区的情况下,你必须扫描所有的500百万条logging,甚至可以获取一个国家的一千个条目。 如果您根据国家/地区对表格进行分区,则可以通过仅检查一个国家/地区分区的数据来优化查询过程。 Hive分区为列(S)值创build一个单独的目录。
优点:
- 水平分配执行负载
- 在数据量较小的分区情况下,更快地执行查询。 例如,从“ 梵蒂冈城 ”获得人口回报非常快,而不是search整个世界人口。
缺点:
- 太多的小分区创作的可能性 – 目录太多。
- 对于给定分区的低容量数据有效。 但是像大量数据一样的查询仍然需要很长时间才能执行。 比如梵蒂冈城人口分组比较需要很长时间。 在数据倾向于特定分区值的情况下,分区不能解决响应性问题。
蜂巢Bucketing:
Bucketing将数据分解为更易于pipe理或相同的部分。
通过分区,您可以根据列值创build多个小分区。 如果您selectbucketing,则会限制存储数据的数量。 这个数字是在表创build脚本中定义的。
优点
- 由于每个分区的数据量相同,Map端的连接速度会更快。
- 更快的查询响应,如分区
缺点
- 您可以在创build表格时定义桶的数量,但是等量数据的加载必须由程序员手动完成。
不同之处在于分区按列名划分文件,而分区则在表内的特定值下划分文件
希望我能正确定义它
分区:分区基本上是水平的数据片,可以将大量的数据分割成更多可pipe理的块。
CREATE TABLE customer ( id INT, name STRING, address1 STRING )PARTITION BY (REGION STRING,country STRING );
支持多个“限幅器”或分区列(即地区/国家)。
对于在Hive中分区和分区的区别,请参考此链接