2012-10-07 40 views
3

我有一个表简要结构是这样的:当行数增加时,PostgreSQL查询如何减慢速度?

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秒我会将大于150秒的行“删除”列变为“TRUE”。

+0

'主键'意味着'非空',所以后面的不是必需的 –

回答

4

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

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

给出的建议也应适用:

例如,您可能:

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

这包括仅在索引行deleted = 'f'(假设deleted是'不为空)。这与让他们完全离开桌子不一样。

  • 全表顺序扫描没有什么变化,仍然需要扫描deleted='t'行;和
  • 还有更多的I/O比如果deleted = 't'行不存在,因为任何给定的堆页可能包含deleted = 't'deleted = 'f'行的混合。

您可以通过CLUSTER降低包含deleted的索引对后者的影响。再一次,这对顺序扫描没有影响。为了帮助顺序扫描,您必须将表格分区为deleted

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

请注意,您需要控制表和索引膨胀。确保autovaccum非常频繁地运行,并使用当前版本的PostgreSQL,它不需要像手动管理的免费空间映射那样的东西,并具有最新的,最佳行为的自动清理。我建议9.0或以上,最好是9.1或9.2。调整自动清理以积极运行。

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

+0

+1,但我会说一个部分索引* *不*删除;-) –

+0

@ MichaelKrelin-黑客嗯,哎呀。固定。 –

+0

对不起,选择你,但在例子中,你说'when',而不是'where';-) –