我们有一个应用程序,用于收集基于时间戳的数据。由于一个月的数据超过 3000 万行(并且每个月都在增长),我们决定按年和月对数据进行分区。
我们基本上有一个主表和分区表,如 master_y2013m01 等。由于我们的应用程序堆栈,我们使用插入前触发器将行插入到正确的分区和主表中,然后使用插入后触发器从主表中删除它们(我们需要原始插入来返回插入的行信息)。
这意味着主表很快就会被死元组填充,并频繁触发自动清理(我们使用自动清理的默认设置)。
将数据库从 PostgreSQL 8.4 升级到 9.1 后,我们注意到 IO 大幅增加,并将其追溯到自动清理:iotop 报告 4-6M/s 的突发速度需要 90 秒,随后暂停 30 秒。这是需要仔细研究的大量数据,尤其是因为主表只有几兆字节(包括索引)。
谁能解释为什么会发生这种情况以及我们该如何解决它?
答案1
和Postgres 开发人员的帮助我们找到了答案,似乎自 9.0 以来,ANALYZE 在父表上运行也会在子表上运行。由于我们的用例经常触发自动清理,因此在运行之前也会触发 ANALYZE,并且它还会分析子表。
我们决定使用更大的自动清理阈值:
ALTER TABLE ... SET (autovacuum_analyze_threshold = ...);
这将降低 ANALYZE 频率并保持我们的 IO、CPU WAIT 和 LOAD 值较低。