24

根据手册中的这一indexes don't need to be maintained. 但是,我们正在使用具有连续速率的 PostgresQL 表运行updatesdeletes并且inserts随着时间的推移(几天),查询性能会显着下降。如果我们删除并重新创建索引,查询性能就会恢复。

我们正在使用开箱即用的设置。
我们测试中的表目前一开始是空的,并且增长到 50 万行。它有一个相当大的行(很多文本字段)。

我们是searching based of an index, not the primary key(我已经确认正在使用该索引,至少在正常情况下是这样)

该表被用作单个进程的持久存储。在带有 Java 客户端的 Windows 上使用 PostgreSQL。

我愿意放弃insert and update performance以保持查询性能。

我们正在考虑重新架构应用程序,以便数据以允许我们定期删除和重建索引而不影响应用程序的方式分布在各种动态表中。但是,与往常一样,要使其正常工作需要时间,我怀疑我们在配置或使用中缺少一些基本的东西。

我们已经考虑了forcing vacuumingand rebuild to run at certain times,但我怀疑locking period for such an action would cause our query to block. 这可能是一个选项,但有一些实时(3-5 秒的窗口)影响需要我们的代码进行其他更改。

附加信息: 表格和索引

CREATE TABLE icl_contacts
(
  id bigint NOT NULL,
  campaignfqname character varying(255) NOT NULL,
  currentstate character(16) NOT NULL,
  xmlscheduledtime character(23) NOT NULL,
...
25 or so other fields.  Most of them fixed or varying character fiel  
...
  CONSTRAINT icl_contacts_pkey PRIMARY KEY (id)
)
WITH (OIDS=FALSE);
ALTER TABLE icl_contacts OWNER TO postgres;

CREATE INDEX icl_contacts_idx
  ON icl_contacts
  USING btree
  (xmlscheduledtime, currentstate, campaignfqname);

分析:

Limit  (cost=0.00..3792.10 rows=750 width=32) (actual time=48.922..59.601 rows=750 loops=1)
  ->  Index Scan using icl_contacts_idx on icl_contacts  (cost=0.00..934580.47 rows=184841 width=32) (actual time=48.909..55.961 rows=750 loops=1)
        Index Cond: ((xmlscheduledtime < '2010-05-20T13:00:00.000'::bpchar) AND (currentstate = 'SCHEDULED'::bpchar) AND ((campaignfqname)::text = '.main.ee45692a-6113-43cb-9257-7b6bf65f0c3e'::text))

而且,是的,我知道有各种各样的事情we could do to normalize and improve the design of this table。其中一些选项可能对我们可用。

我在这个问题上的重点是理解how PostgresQL is managing the index and query over time (understand why, not just fix)。如果要重新完成或进行重大重构,将会有很多变化。

4

5 回答 5

16

自动真空应该可以解决问题,前提是您将其配置为所需的性能。

注意: VACUUM FULL:这将重建表统计信息并回收磁盘空间负载。它锁定了整个表。

VACUUM:这将重建表统计信息并回收一些磁盘空间。它可以与生产系统并行运行,但会产生大量影响性能的 IO。

ANALYZE:这将重建查询计划器统计信息。这是由 VACUUM 触发的,但可以单独运行。

详细的注释在这里找到

于 2010-03-08T15:08:39.203 回答
4

这对我来说就像索引膨胀。我会推荐你​​到这个页面

http://www.postgresql.org/docs/8.3/static/routine-reindex.html

在底部说:

此外,对于 B 树索引,新构建的索引比多次更新的索引访问速度要快一些,因为在新构建的索引中,逻辑上相邻的页面通常也是物理上相邻的。(此注意事项目前不适用于非 B 树索引。)为了提高访问速度,定期重新索引可能是值得的。

这似乎与您引用的页面冲突,即索引“不需要维护或调整”。

您是否尝试过“同时创建索引”?

于 2011-04-19T01:38:11.890 回答
3

至于性能,使用字符串存储时间和状态信息是一个相当大的瓶颈。首先,文本索引效率极低,同一天比较两次至少需要11次比较(以您使用的格式),但是,使用时间类型可以简化为一次比较。这也会影响索引的大小,并且很难搜索大索引,并且数据库不会将其保存在内存中。同样的考虑也适用于 state 列。如果它代表一小组状态,您应该使用映射到状态的整数,这将减少索引的节点 - 并相应地减少索引大小。此外,如果您未在查询中指定实际时间,即使使用这些内置类型,该索引也将毫无用处。

于 2011-04-17T06:08:54.110 回答
2

正在比较 xmlscheduledtime 的“2010-05-20T13:00:00.000”值是 SQL 的一部分还是作为参数提供?

在计划如何运行查询时,说一个字段必须小于提供的具有未知值的参数,这并没有给 PostgreSQL 提供太多帮助。它不知道这是否会匹配几乎所有的行,或者几乎没有任何行。

阅读规划器如何使用统计数据有助于弄清楚为什么您的数据库正在使用它的规划。

您可以通过更改该复杂索引中的字段顺序或创建一个新索引来获得更好的选择性能,这些字段已排序(campaignfqname、currentstate、xmlscheduledtime),因为那时索引将带您直接进入活动 fq 名称和当前状态您感兴趣的,并且 xmlscheduledtime 范围内的索引扫描都将是您所追求的行。

于 2010-03-08T20:06:10.587 回答
1

那是教科书式的案例。您应该将 autovacuum 设置为更具侵略性。

于 2011-05-03T21:34:50.310 回答