当行数增加时,这个PostgreSQL查询如何减慢?

时间:2012-10-07 09:39:35

标签: postgresql optimization

我有一个简短的结构表:

tn( id integer NOT NULL primary key DEFAULT nextval('tn_sequence'),
                 create_dt TIMESTAMP NOT NULL DEFAULT NOW(),
                             ...............
                 deleted boolean );

create_dt是将行插入数据库的时间戳。

deleted表示该行已经或不再有用。

我有以下疑问:

select * from tn where create_dt > ( NOW() - interval '150 seconds ) and deleted = FALSE;
select * from tn where create_dt < ( NOW() - interval '150 seconds ) and deleted = FALSE;

我的问题是当行数增加时这些查询会如何减慢?例如,当行数超过10K,20K或100K时,它会对速度产生很大影响吗?有什么方法可以优化这些查询吗?请注意,我每5秒钟会将列删除&#39;超过150秒的行&#39; TRUE&#39;。

1 个答案:

答案 0 :(得分:4)

表增长对性能的影响取决于所选的查询计划,可用索引,查询的选择性以及许多其他因素。查询EXPLAIN ANALYZE可能有所帮助。简而言之,如果您的查询只选择几行并且可以使用简单的b-tree索引,那么它通常不会减慢吨数,只会随着索引的增长而减慢。另一方面,使用复杂的非索引条件或返回大量行的查询可能会非常糟糕。

您的问题似乎反映在问题How should we handle rows which won't be queried once they are old in PostgreSQL?

那里给出的建议应该适用:

  • 使用条件为WHERE (not deleted)的{​​{3}};或
  • 在启用了partial index的情况下,“已删除”
  • partition

例如,您可以:

CREATE INDEX create_dt_when_not_deleted_idx 
ON tn (create_dt)
WHERE (NOT deleted);

这仅包括索引中deleted = 'f'(假设deleted为非空)的行。这与将它们完全从桌子上消失是不一样的。

  • 全表顺序扫描没有任何变化,仍然必须扫描deleted='t'行;和
  • I / O比没有deleted = 't'行的I / O多,因为任何给定的堆页面可能包含deleted = 't'deleted = 'f'行的混合。

您可以CLUSTER对包含deleted的索引减少后者的影响。同样,这对顺序扫描没有影响。要帮助进行顺序扫描,您必须在deleted上对表进行分区。

Pg 9.2的索引扫描应该(我认为,尚未测试)使用部分索引。当只能进行索引扫描时,部分索引应该与仅包含deleted = 'f'行的表上的索引一样快。

请注意,您需要控制表和索引膨胀。确保autovaccum非常频繁地运行并使用当前版本的PostgreSQL,它不需要手动管理的自由空间映射,并且具有最新的,性能最好的autovacuum。我推荐9.0或以上,最好是9.1或9.2。调整autovacuum积极运行。

调整和测试效果时 - 使用EXPLAIN ANALYZE测试您的查询,不要只是猜测。