欢迎阅读 TimescaleDB 最佳实践系列的第二部分!在第一部分中,我们探讨了如何高效地执行大规模回填操作,并分享了一些优化性能和避免常见陷阱的技巧。如果您还没有阅读第一部分,可以通过此链接查看。
在今天的博客中,我们将讨论时间序列数据管理的另一个重要方面:大规模删除操作。
随着数据随着时间的推移而增长,旧记录往往会失去其相关性,但会继续占用宝贵的磁盘空间,从而可能增加存储成本,如果管理不善,可能会降低性能。
让我们介绍一些清理或减少 TimescaleDB 中老化数据的策略,帮助您维护精简、高效且经济高效的数据库。
大规模删除操作的先决条件
以下是在生产中执行大规模删除时需要遵循的几个重要步骤,以确保我们在出现问题时做好准备。
调整 Autovacuum 设置
在 PostgreSQL 中,VACUUM是一个维护过程,用于移除死元组(UPDATE或DELETE操作留下的过时行版本)。这些死元组会占用空间,但对任何活动事务都不再可见。Vacuum 操作可以回收这些空间,有助于减少表膨胀并维护数据库性能。
自动清理功能会定期在后台运行,自动执行此过程,确保无需人工干预即可清理死行。这在执行大量删除操作后尤为重要,因为此时会累积大量死行。如果不及时处理,可能会导致表膨胀、I/O 增加以及查询性能下降。
然而,它的有效性很大程度上取决于配置的合理性。如果没有适当的调整,自动清理可能会运行频率过低或速度过慢,从而导致死元组堆积并影响性能。
以下是一些重要的自动清理参数及其推荐值的列表,可用于有效地调整自动清理。
自动清理
- 描述:启用或禁用自动清理守护进程。
- 默认值:开启
- 建议:开启
autovacuum_max_workers
- 描述:指定自动清理工作进程的最大数量。
- 默认值:3
- 建议:CPU 核心/8,但至少 3
- 例如:如果 PostgreSQL 分配了 56 个 CPU 核心,则该值应为 56/8 = 7
autovacuum_naptime
- 描述:自动清理运行之间的时间间隔。
- 默认值:1分钟
- 建议:30秒
autovacuum_vacuum_scale_factor
- 描述:表大小的分数,决定了触发真空所需的更新或删除的元组的额外数量。
- 默认值:0.2
- 建议:0.05
autovacuum_analyze_scale_factor
- 描述:表大小的分数,决定触发分析所需的更新或插入元组的额外数量。
- 默认值:0.1
- 建议:0.05
autovacuum_vacuum_cost_delay
- 描述:自动清理工作者执行清理操作之间的成本延迟(以毫秒为单位)。
- 默认值:20ms
- 建议:100ms
autovacuum_vacuum_cost_limit
- 描述:自动清理工作者执行清理操作的成本限制。
- 默认值:-1(使用vacuum_cost_limit)
- 建议:2000
log_autovacuum_min_duration
- 描述:如果自动清理操作所用时间超过指定的持续时间(以毫秒为单位),则记录该操作。
- 默认值:-1(禁用)
- 建议:1000ms
autovacuum_work_mem
- 描述:自动清理工作者处理每个表时使用的内存。
- 默认值:-1(使用 maintenance_work_mem)
- 建议:系统内存的 20% / autovacuum_max_workers
- 示例:如果 PostgreSQL 分配了 300GB 内存,并且 autovacuum_max_workers 为 10,则该值应为 300 / 10 = 6 GB 的 20%。
执行大规模删除操作的方法
在本节中,我们将介绍在生产环境中执行大规模删除操作的几种关键方法。但是,强烈建议在将所选方法应用到生产系统之前,先在暂存环境中进行测试。
方法 1:使用 TimescaleDB 的数据保留策略
要执行大规模删除操作,Timescale 建议使用数据保留策略。数据保留策略会自动删除旧数据,从而帮助您节省存储成本。
数据保留策略意味着,一旦数据的时间值超过一定时间间隔,它就会自动删除数据。当我们创建数据保留策略时,Timescale 会自动安排后台作业来删除旧的数据块。
这就是我们可以添加数据保留策略的方法
SELECT add_retention_policy('test_table', INTERVAL '10 months');
在上面的例子中,我们在名为test_table的超表上创建了一个数据保留策略,指定任何超过10 个月的数据都应自动删除。
方法 1.1:使用保留策略和连续聚合对数据进行下采样
较旧的历史数据通常会被保留下来,以支持未来的分析需求,即使这些数据何时或如何使用尚不明确。因此,这些数据通常不会被删除,从而导致存储消耗随着时间的推移而增加。
为了解决这个问题,Timescale 提供了一种解决方案,允许删除数据,同时仍以聚合形式保留以供历史分析。这可以通过结合保留策略和连续聚合来实现。
这意味着我们可以从超表中删除旧数据,而无需将其从任何连续聚合中删除。这种方法可以节省原始数据的存储空间,同时保留汇总数据以供历史分析。
使用此方法时,仔细配置与数据保留策略相关的连续聚合的 刷新间隔至关重要。
例如,如果您将数据保留策略设置为删除超过1 天的数据,并且连续聚合也配置为每1 天刷新一次,则存在刷新所需的原始数据在刷新发生时已被删除的风险。因此,连续聚合可能无法访问必要的数据,从而导致数据不完整或无用。
为避免这种情况,请始终确保数据保留期长于连续聚合的刷新窗口。这样,系统就有足够的时间在原始数据被删除之前更新聚合。
方法 2:在 TimescaleDB 中手动删除块
如果您希望更好地控制删除过程,并且更愿意手动管理而不是使用自动数据保留策略,则此方法可能更适合您。它允许您根据特定需求和要求选择和删除数据块。
从性能角度来看,使用 PostgreSQL DELETE命令逐行删除数据可能很慢。但按块删除数据会更快,因为它会从磁盘删除整个文件。它不需要垃圾收集和碎片整理。
您可以使用以下命令手动删除一个块:
SELECT drop_chunks('test_table', INTERVAL '24 hours');
这将从test_table hypertable中删除包含超过24 小时的数据块
方法 3:将选定的数据传输到新的 Hypertable
此方法在需要从超表中删除大量数据的情况下尤其有用,通常是当很大一部分数据不再需要时。与逐行删除或依赖保留策略相比,此方法可以实现更可控、更高效的清理。
以下是涉及的步骤
- 定义一个具有相同模式的新超表,包括所有必要的列、索引和约束。
- 仅将原始超表中相关或所需的数据子集插入/复制到新的超表中。这允许您在复制过程中丢弃不需要的数据。
- 执行健全性检查或数据验证,以确保所有必要的数据都已准确地传输到新的超表。
- 验证完成后,如果您对数据完整性有信心,请删除原始超表以回收存储。
当您能够明确定义哪些数据需要保留,并且现有数据中的大部分不再需要时,此方法最为有效。相比传统的删除方法效率低下或速度缓慢的情况,这种方法能够彻底清除数据,并有助于减少数据膨胀。
执行大规模删除操作后该怎么办
执行大规模删除操作后,建议在超表上运行VACUUM FULL,通过删除死元组并将释放的空间返回给操作系统来回收磁盘空间。
以下是您可以运行的方法
VACUUM FULL test_table
其中test_table是超表名称
结论
最后,我们建议遵循社区制定的指南,在超表上执行大规模删除操作。此外,请确保您的自动清理设置已正确调整,以便高效处理死元组并顺利回收存储。
原文地址:https://stormatics.tech/blogs/best-practices-for-timescaledb-massive-delete-operations
原文作者:Semab Tariq




