InfluxDB 3.0 中用于查询性能的数据分区
作者:Nga Tran / 开发者
2024年1月19日
导航至
查询性能在任何数据库中都至关重要。数据分区是一种有助于修剪不必要数据的机制,从而使查询运行得更快。然而,分区数量的多少总是存在权衡。例如,在高基数列上进行细粒度分区可能会降低性能。本文介绍了 InfluxDB 3.0 支持的不同分区方案,并解释了它们的权衡。
只有 InfluxData 的 Cloud Dedicated 和 Clustered 产品支持用户定义的分区。请注意,InfluxDB Cloud Serverless 始终按天对数据进行分区,并且无法修改。
默认分区
由于 InfluxDB 是一个时间序列数据库,它会按时间范围过滤大多数查询。如果您在加载数据时未指定表的partition方式,默认情况下,InfluxDB 会按天对数据进行分区,如图 1 所示。它将同一天 time 列的所有数据存储在同一分区中。在实践中,对于大多数中等数据量的用例,这是一种很好的分区方案,有助于平衡摄取效率和查询性能。
图 1:按天分区的 my_table 数据
选择特定时间范围的查询只需要从相关的分区读取数据。例如,以下 SQL 查询只需要读取两个分区的数据,即 2025-01-01 和 2025-01-02。InfluxDB 3.0 使用来自其目录的信息来避免读取任何其他分区。
SELECT ...
FROM my_table
WHERE time >= '2025-01-01 18:00:00' AND time <= '2025-01-02 03:00:00';
查询 1:按时间范围过滤数据
用户定义 / 自定义分区
对于单天包含过多数据(例如,GB 级的 Parquet 文件),并且查询包含对其他标签列的过滤的情况,InfluxDB 允许您根据标签和时间对数据进行分区。例如,如果您的常用查询请求特定城市在特定时间范围内的数据,如下面的查询所示,则可以使用自定义分区根据 city_name 和 time 对数据进行分区。
SELECT ...
FROM my_table
WHERE time >= '2025-01-01 18:00:00' AND time <= '2025-01-02 03:00:00'
AND city_name = `Boston`;
查询 2:按城市和时间范围过滤数据
如果您按 city_name 和 day 对数据进行分区,您将拥有更多的分区,它们将如下所示
图 2:按 city_name 和 day 分区的 my_table 数据
查询 2 只需要读取两个分区,即 Boston | 2025-01-01 和 Boston | 2025-01-02。如果您的数据包含许多城市,则每个分区将比默认的按天分区小,并且您的查询需要读取的数据量也会更少。
请注意,您的自定义分区标签列必须始终具有值,InfluxDB 才能将其存储在正确的分区中。如果没有值,InfluxDB 将没有足够的信息来应用过滤器,并且您的查询最终将读取所有分区。
分区过多的代价
分区设计总是伴随着权衡。虽然较小的分区有助于减少查询读取的数据量,但这并不总是意味着您的查询会运行得更快。对数据摄取器和压缩器的工作负载也有副作用。拥有较小的分区通常意味着拥有更多、更小的 Parquet 文件,这将导致
- 存储效率降低——更多文件需要更多空间来存储相同的数据。
- 需要更高的摄取器工作负载才能将数据分组到更小的分区和文件中。
- 需要更高的压缩器工作负载才能压缩更多的分区和更小的文件。
- 更高的元数据目录量——更多的分区和更多的文件需要在查询时进行更多的修剪处理。
- 不包含谓词且覆盖整个分区设计的查询最终可能会读取许多分区和更小的文件,从而降低性能。
以下是您可以控制分区数量的方案。
用户控制的分区数量
如果您想控制包含许多城市的数据集的分区数量,但每个城市的数据量不多,您可以考虑在更大的时间范围内对数据进行分区。图 3 说明了按 city_name 和 month 分区的数据。在这种情况下,查询 2 将读取一个分区的数据,即 Boston | 2025-01,它涵盖了波士顿整个月份的数据。
图 3:按 city_name 和 month 分区的 my_table 数据
注意:为特定时间定义保留策略允许您控制数据库中的分区数量。
用户定义的分区数量
在撰写本文时(2024 年 1 月),InfluxData 正在开发一项名为“服务器端分桶”的功能,该功能将为用户提供一种更简单的方法来设置他们期望的分区数量。例如,如果您不知道数据集将包含多少个城市,但您知道会很多,则可以通过将许多城市哈希到同一分区中来限制分区数量。图 4 显示了按 hash(city_name) % 10 和 day 分区的数据。在这种情况下,一年数据最多将有 10 * 365 = 3,650 个分区。
图 4:按 hash(city_name) % 10 和 day 分区的 my_table 数据。
最终想法
为您的数据找到合适的分区方案有助于提高查询性能,尤其是在高容量摄取的情况下。但是,您需要了解数据的性质和规模,才能实施正确的设计并确保系统中不会有太多分区。请记住避免根据可选的标签值对数据进行分区。如果您的数据缺少值,InfluxDB 将没有足够的信息来应用过滤器,并且您的查询最终将读取所有分区。
有关数据分区的其他作用,请参阅 Partitioning for Performance in a Sharding Database System。