我们正在运行Postgres 9.1.3,并且我们最近开始在我们的一台服务器上遇到重大性能问题。
我们的查询运行良好一段时间,但截至8月1日,它们已经大幅放缓。似乎大多数有问题的查询都是Select查询(带有count(*)的查询特别糟糕),但一般情况下,数据库的运行速度非常慢。
我们在服务器上运行this查询,这些是我们对默认配置文件所做的更改(注意:之前服务器运行正常,因此,它们可能无关紧要) :
name | current_setting
---------------------------+---------------------------------------------------------------------------------------------------------------
version | PostgreSQL 9.1.2 on x86_64-unknown-linux-gnu, compiled by gcc (GCC) 4.1.2 20080704 (Red Hat 4.1.2-51), 64-bit
autovacuum | off
bgwriter_delay | 20ms
checkpoint_segments | 6
checkpoint_warning | 0
client_encoding | UTF8
default_statistics_target | 1000
effective_cache_size | 4778MB
effective_io_concurrency | 2
fsync | off
full_page_writes | off
lc_collate | en_US.UTF-8
lc_ctype | en_US.UTF-8
listen_addresses | *
maintenance_work_mem | 1GB
max_connections | 100
max_stack_depth | 2MB
port | 5432
random_page_cost | 2
server_encoding | UTF8
shared_buffers | 1792MB
synchronous_commit | off
temp_buffers | 16MB
TimeZone | US/Eastern
wal_buffers | 16MB
wal_level | minimal
wal_writer_delay | 10ms
work_mem | 16MB
(28 rows)
Time: 210.231 ms
通常,当出现这样的问题时,人们首先推荐的是吸尘,我们已经尝试过。我们对大部分数据库进行了真空分析,但没有帮助。
我们在一些查询中使用了Explain
,并注意到Postgres正在使用顺序扫描,即使这些表有索引也是如此。
我们关闭顺序扫描以强制查询计划程序使用索引,但这也没有帮助。
然后我们尝试了this查询,看看我们是否有很多未使用的磁盘空间,Postgres正在经历这些磁盘空间以查找它正在寻找的内容。不幸的是,虽然我们的一些表确实有点大量,但它似乎不足以降低整体系统性能。
我们认为减速可能与I / O有关,但我们无法弄清楚具体细节。 Postgres是愚蠢的,如果是的话,它的哪一部分? VM有什么问题,或者物理硬件本身可能有问题吗?
你们对我们可以尝试或检查的事情有任何其他建议吗?
编辑:
我很抱歉没有尽快更新。我被其他事情搞砸了。
在这台特定的机器上,通过对虚拟机的设置进行一次小的修改,我们的性能得到了极大的提升。
有一个处理IO缓存的设置。它最初设置为ON。我们认为不断缓存事情会减慢事情的速度,我们是正确的。我们把它关掉了,事情急剧改善。
有趣的是,我们大多数其他服务器已关闭此设置。
还有其他问题,我相信我们会提出很多建议,所以,非常感谢您的帮助。
答案 0 :(得分:13)
你最大的问题是这一行:
autovacuum | off
打开它不会立即解决问题,但它应该防止事情进一步恶化。几乎没有任何情况下关闭它是个好主意。主要的例外是大量装载,然后是明确的VACUUM FREEZE ANALYZE,之后应该重新打开autovacuum。关闭autovacuum后,您将看到性能下降,就像您一样。一旦数据库变得如此糟糕,它需要比autovacuum可以提供的更积极的维护来恢复。
checkpoint_segments | 6
增加此值有助于数据修改,但不会提高SELECT
语句的速度。
fsync | off full_page_writes | off
这些设置告诉PostgreSQL以牺牲持久性为代价来加速写入。如果您的硬件或操作系统(或VM)崩溃或突然被杀,您的数据库将被破坏,最好的办法是从上次已知的良好备份中恢复。 (当然,由于硬件可能随时出现故障,如果您担心丢失数据,则可以采用良好的备份策略。)
maintenance_work_mem | 1GB
这对于8GB的VM而言太高了。在对该连接运行一些繁重的维护之前,您始终可以在单个连接上对其进行增强。
wal_writer_delay | 10ms
即使是经验丰富的专家也难以将其调整为比默认值更好的性能。几乎总是最好不要管它。
此时最好的办法是使用pg_dumpall将数据库集群转储到其他介质,从新的initdb开始,然后恢复。作为数据库超级用户,运行VACUUM FREEZE ANALYZE
(通常不建议使用FREEZE
,除非在此类批量加载之后),并且在启用autovacuum的情况下运行。
我强烈建议您获得Greg Smith的“PostgreSQL 9.0高性能”一书的副本,并仔细阅读。 (完全披露,我是这本书的技术评论员之一,但没有从销售中获得金钱。)他建议的第一件事就是在你安装PostgreSQL之前获得RAM和磁盘速度的基准数字 - 那个你知道你在做什么的方式。
答案 1 :(得分:10)
很难确定,但我认为你对I / O问题持怀疑态度是正确的。可能发生的是,随着表变大或连接增加,缓存命中率开始下降。这会增加I / O需求并减慢一切。同时,更多的查询到达,使问题变得更糟。这种情况对您来说很复杂,因为虚拟磁盘的行为不一定与物理磁盘相同。
首先,您需要测量VM上的实际活动(可能通过vmstat或iostat)。其次,在真实硬件上做同样的事情。最后,在两者上运行一些标准磁盘带宽工具(特别是随机读/写混合)。现在,您可以说明您正在使用的可用I / O的数量。
至于查询计划,没有架构细节和解释分析输出,没有人可以说。
你会发现postgresql.org邮件列表很有用,即使只是为了档案。此外,下面链接的书非常好。
答案 2 :(得分:2)
答案 3 :(得分:0)
我也打开自动吸尘器。您可以设置一些变量来控制真空干扰的程度。使用大量的RAM,您应该将共享缓冲区设置在2048MB到3276MB之间。如果您的系统似乎没有使用大量额外的RAM,而您在其他地方并不需要,那么您应该将其设置为更接近更高端。您也可以使用sysctl查看最大段大小。你的maintenance_work_mem真的很高,但是如果你主要做的是维护,那么我认为它没有我想象的那么糟糕。