Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/postgresql/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Performance 为什么PostgresQL查询性能会随时间下降,但在重建索引时会恢复_Performance_Postgresql_Indexing_Sql Tuning - Fatal编程技术网

Performance 为什么PostgresQL查询性能会随时间下降,但在重建索引时会恢复

Performance 为什么PostgresQL查询性能会随时间下降,但在重建索引时会恢复,performance,postgresql,indexing,sql-tuning,Performance,Postgresql,Indexing,Sql Tuning,根据手册中的说明,索引不需要维护。但是,我们运行的PostgresQL表具有连续的更新、删除和插入,随着时间的推移(几天),查询性能会显著下降。如果我们删除并重新创建索引,查询性能就会恢复 我们正在使用现成的设置。 我们测试中的表目前开始是空的,并且增长到50万行。 它有一个相当大的行(许多文本字段) 我们基于索引而不是主键进行搜索(我已经确认索引正在使用,至少在正常情况下是这样) 该表被用作单个进程的持久存储。 在Windows和Java客户端上使用PostgresQL 我愿意放弃插入和更新性

根据手册中的说明,
索引不需要维护
。但是,我们运行的PostgresQL表具有连续的
更新
删除
插入
,随着时间的推移(几天),查询性能会显著下降。如果我们删除并重新创建索引,查询性能就会恢复

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

我们基于索引而不是主键进行搜索(我已经确认索引正在使用,至少在正常情况下是这样)

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

我愿意放弃
插入和更新性能
,以保持查询性能

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

我们已经考虑过在特定时间强制执行
真空清理
重建
,但我怀疑这样一个操作的
锁定期会导致我们的查询被阻止。这可能是一种选择,但有一些实时(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))
限制(成本=0.00..3792.10行=750宽度=32)(实际时间=48.922..59.601行=750循环=1)
->使用icl_触点上的icl_idx进行索引扫描(成本=0.00..934580.47行=184841宽度=32)(实际时间=48.909..55.961行=750圈=1)
索引条件:((xmlscheduledtime<'2010-05-20T13:00:00.000'::bpchar)和(currentstate='SCHEDULED'::bpchar)和((活动FQName::text='.main.ee45692a-6113-43cb-9257-7b6bf65f0c3e'::text))
是的,我知道我们可以做很多事情来规范和改进这个表的设计。我们可能可以使用其中一些选项


我在这个问题上的重点是了解
PostgresQL如何随时间管理索引和查询(了解原因,而不仅仅是修复)
。如果要对其进行重做或显著重构,将会有很多更改。

自动真空应该可以做到这一点,前提是您根据所需的性能对其进行了配置

注: 真空满:这将重建表统计信息并回收磁盘空间负载。它锁着整张桌子

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

分析:这将重建查询计划器统计信息。这是由真空触发的,但可以自行运行


更多

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

在计划如何运行查询时,如果说字段必须小于提供的参数,并且具有未知值,则PostgreSQL将无法继续。它不知道这是否会匹配几乎所有的行,或者几乎不匹配任何一行

当试图弄清楚数据库为什么使用它现在的计划时,阅读关于的内容会有很大帮助


通过更改该复杂索引中字段的顺序,或创建一个新索引,并对字段进行排序(活动FQName、currentstate、xmlscheduledtime),您可能会获得更好的select性能,因为该索引将直接指向您感兴趣的活动fq名称和当前状态,在xmlscheduledtime范围内的索引扫描都将是您要查找的行。

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

我觉得这有点像索引膨胀。我让你看看这一页

下面写着:

同样,对于B树索引a 新构造的索引有点复杂 访问速度比具有 已更新多次,因为 逻辑上相邻的页面通常是 在一个新的环境中也物理上相邻 建立索引。(考虑到这一点 当前不适用于非B树 这可能值得一试 定期重新编制索引以提高性能 访问速度

这似乎与您引用的页面所说的索引“不需要维护或调整”相冲突


您是否尝试过“并发创建索引”

这是教科书上的案例。您应该将autovacuum设置为更具攻击性。

您使用的是什么版本?当你滥用真空满时,你的索引膨胀,你必须重新编制索引。忘记开箱即用的设置,这是不会执行的。你必须配置你的数据库,告诉它如何使用内存,做自动真空等。没有配置,没有性能。你使用的是什么版本?你…吗