使用基于 CTID 的分页在 PostgreSQL 中进行数据清理

主要观点:处理 15TB 以上的 PostgreSQL 大表时,常规数据归档任务极具挑战,即使有良好索引也如此。
关键信息:

  • 初始采用基于标准 ID 的分页删除数据方法会超时,因数据库需扫描索引找旧记录、按 ID 排序、执行删除及维护索引,15TB 大表的查找操作昂贵。
  • PostgreSQL 中每行有表示物理位置的 CTID(page_number 和 row_number),利用其可按页顺序处理表,如通过WITH to_delete AS语句选择特定 CTID 范围的行进行删除,查找快速且不影响系统。
  • 完整清理的 Ruby/Rails 示例代码,使用REPEATABLE READ隔离来处理 CTID 稳定性问题,以可预测的物理存储块处理表,避免昂贵索引操作,维持数据库负载稳定。
  • 该方法虽比基于索引的删除慢,但可靠、快速且不影响系统,可定期运行ANALYZE
  • 单纯强制 PostgreSQL 使用顺序扫描不能解决超时问题,仍需顺序扫描每行。
    重要细节:
  • 代码示例中的各种 SQL 语句及操作细节,如BETWEEN条件、FOR UPDATE SKIP LOCKED等的作用。
  • 强调在可能时使用索引,此案例中因特殊情况采用 CTID 分页作为临时缓解措施,且提及分区虽有帮助但因查询模式等原因目前不易实现,还介绍了在新工具pg_flo中使用 CTID 分页。
阅读 73
0 条评论