数据分区和分桶:现代数据系统如何组织和优化您的数据

随着数据量的持续增长,高效的数据组织对于性能、可扩展性和成本管理变得至关重要。构建大数据的两种最有效策略是分区分桶。尽管它们经常一起被提及,但它们服务于不同的目的,并且以不同的方式实现。本文提供了一个实用的、详细的视角,介绍这些技术如何工作、它们对存储的影响以及如何在数据管道中有效地使用它们。

什么是数据分区?

分区是根据一个或多个列(分区键)的值将大型数据集划分为较小的、更易于管理的段。每个分区通常在存储系统(如 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 也支持一些模式演变。

何时使用分区与分桶

  • 分区:最适合在特定列(例如日期、区域)上进行过滤的查询。减少扫描的数据并提高并行性。
  • 分桶:最适合在高基数列上进行高效的连接或采样。确保均匀的数据分布并可以加快连接操作。

总结表:分区与分桶

分区分桶
目的根据特定列值划分数据,便于过滤根据哈希函数将数据划分到固定数量的桶中,便于连接和采样
存储方式每个分区为一个目录每个桶为一个文件
对性能的影响减少扫描的数据量,提高并行性确保数据均匀分布,加快连接操作
适用场景过滤查询连接和采样查询
阅读 17
0 条评论