随着数据量的持续增长,高效的数据组织对于性能、可扩展性和成本管理变得至关重要。构建大数据的两种最有效策略是分区和分桶。尽管它们经常一起被提及,但它们服务于不同的目的,并且以不同的方式实现。本文提供了一个实用的、详细的视角,介绍这些技术如何工作、它们对存储的影响以及如何在数据管道中有效地使用它们。
什么是数据分区?
分区是根据一个或多个列(分区键)的值将大型数据集划分为较小的、更易于管理的段。每个分区通常在存储系统(如 HDFS、S3 或云对象存储)中作为一个单独的目录存储。
分区在存储中的工作方式
- 每个分区是主表目录下的一个子目录。
- 每个分区包含仅包含与其特定键相关联的数据的文件。
- 查询引擎如果查询过滤器排除了某个分区,则可以跳过整个分区,减少扫描的数据量并提高性能。
示例:按年和月对销售表进行分区,创建一个目录结构,如/year=2025/month=07/
,2025 年 7 月的所有数据都存储在该目录中。
分区的最佳实践
- 选择与常见查询过滤器匹配的分区键(例如日期、区域)。
- 避免过度分区(创建太多小分区),这可能导致过多的元数据开销并减慢查询速度。
- 监控分区大小,以避免数据倾斜并确保均衡的工作负载。
什么是分桶?
分桶(或聚类)使用一个或多个列(桶键)上的哈希函数将数据划分为固定数量的桶(文件)。与分区不同,分区为每个唯一值创建一个目录,分桶为每个分区或表创建固定数量的文件,更均匀地分布数据。
分桶在存储中的工作方式
- 每个桶是分区目录(或未分区时的主表目录)中的一个文件。
- 桶键的值被哈希,哈希模桶的数量决定了行存储的文件。
- 分桶对于优化连接和采样特别有用,因为具有相同桶键的行将始终在同一个文件中。
示例:用户活动表可能按用户 ID 分桶为 1024 个桶,确保给定用户的所有记录都存储在一起。
分桶的最佳实践
- 对经常用于连接或聚合的列使用分桶。
- 根据数据大小和查询模式选择桶的数量;太多的桶可能导致小文件和效率低下。(听说过经典的小文件问题吗?)
- 将分桶与分区结合使用,以实现更精细的数据组织。
数据在存储中的组织方式
组合结构
当两种技术一起使用时,存储布局如下:
Shell
/table_name/partition_col1=value1/partition_col2=value2/...
├── 000000_1
├── 000000_2
├──...
└── 000000_n
000000_1、000000_2、...000000_n 是分区(目录/子目录)内的桶(文件)。
示例:按年分区,按客户 ID分桶的表创建:
SQL
CREATE TABLE orders_raw_table (
order_id INT,
customer_id INT,
amount DOUBLE,
order_date STRING
)
PARTITIONED BY (order_year STRING)
CLUSTERED BY (customer_id) INTO 16 BUCKETS
STORED AS ORC;
此表按order_year
(例如 2025)分区,在每个分区中,数据根据customer_id
的哈希值分布到 16 个桶中。每个桶是一个单独的文件,有助于连接和采样性能。数据以 ORC 文件格式存储,以实现高效的存储和查询执行。
高性能的文件格式
列式格式通常最适合分区和分桶数据,特别是用于分析:
- Parquet:广泛使用,非常适合分析查询,支持谓词下推、高效压缩,并且可拆分以进行并行读取。
- ORC:类似于 Parquet,具有更好的压缩和索引,在批量处理中通常最快,特别是在 Hadoop/Hive 环境中。
- Avro:基于行,最适合流式处理和序列化,对于分析效率不高,但对于写密集型工作负载和模式演变非常好。
关键点:
- Parquet 和 ORC 原生支持分区和分桶。
- 它们允许查询引擎跳过无关的列和分区,减少 I/O 并提高速度。
- 避免太多小文件;目标是文件大小与存储系统的块大小匹配(例如 HDFS 为 128 - 256 MB)。
其他考虑因素和最佳实践
- 分区修剪:查询引擎会自动跳过与查询过滤器不匹配的分区,显著提高性能。
- 谓词下推:像 Parquet 和 ORC 这样的列式格式允许查询跳过不匹配过滤器条件的数据块,进一步减少 I/O。
- 平衡分区大小:避免数据倾斜,确保分区大小相似;一个分区中的数据过多可能成为瓶颈。
- 元数据管理:保持数据目录(例如 AWS Glue、Hive Metastore)更新,包含新的分区和桶,以实现高效的查询规划。
- 压缩:定期将小文件合并为大文件,以优化读取性能并减少元数据开销。
- 模式演变:如果数据模式频繁更改,Avro 更灵活,但 Parquet 和 ORC 也支持一些模式演变。
何时使用分区与分桶
- 分区:最适合在特定列(例如日期、区域)上进行过滤的查询。减少扫描的数据并提高并行性。
- 分桶:最适合在高基数列上进行高效的连接或采样。确保均匀的数据分布并可以加快连接操作。
总结表:分区与分桶
分区 | 分桶 | |
---|---|---|
目的 | 根据特定列值划分数据,便于过滤 | 根据哈希函数将数据划分到固定数量的桶中,便于连接和采样 |
存储方式 | 每个分区为一个目录 | 每个桶为一个文件 |
对性能的影响 | 减少扫描的数据量,提高并行性 | 确保数据均匀分布,加快连接操作 |
适用场景 | 过滤查询 | 连接和采样查询 |
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。