Postgres create/restore 在 amazon ec2 上花费大量时间

Postgres create/restore taking lot of time on amazon ec2

我有一个使用 Ubuntu 12.04 的亚马逊 ec2 实例(比如说 S1)(4 核 7GB 内存),这是 运行 我的网络应用 postgresql 9.1。所有 postgres 数据都存储在 100 GB 的不同 ssd 卷(不是根)上。 (现在只写它目前的 26%)。

突然间,从一两天开始,一些 postgres 操作开始占用大量时间。创建命令(52 秒)并恢复数据库(现在 9 分钟,之前最多 50 秒)。

通过 运行 iostat 和 运行 postgres 命令,我可以确认其 ec2 卷的 IOPS 已达到其限制(3 IOPS/GB 等于 100GB 卷的 300 IOPS)。可以在 运行 这个命令 iostat -d 5 -x -p xvdf 之后在下面看到它。

Device:         rrqm/s   wrqm/s     r/s     w/s    rkB/s    wkB/s avgrq-sz avgqu-sz   await r_await w_await  svctm  %util
xvdf              0.35     2.28    1.20  298.99    19.65 13082.19    87.29    23.42   78.03   64.19   78.09   3.29  98.75

Device:         rrqm/s   wrqm/s     r/s     w/s    rkB/s    wkB/s avgrq-sz avgqu-sz   await r_await w_await  svctm  %util
xvdf              0.00     1.80    0.00  297.40     0.00 13067.20    87.88   126.47  420.75    0.00  420.75   3.35  99.76

Device:         rrqm/s   wrqm/s     r/s     w/s    rkB/s    wkB/s avgrq-sz avgqu-sz   await r_await w_await  svctm  %util
xvdf              0.00     1.80    0.00  297.40     0.00 13067.20    87.88   126.32  417.95    0.00  417.95   3.35  99.76

Device:         rrqm/s   wrqm/s     r/s     w/s    rkB/s    wkB/s avgrq-sz avgqu-sz   await r_await w_await  svctm  %util
xvdf              0.00     1.80    0.00  297.80     0.00 13093.60    87.94   131.70  440.82    0.00  440.82   3.36 100.00

Device:         rrqm/s   wrqm/s     r/s     w/s    rkB/s    wkB/s avgrq-sz avgqu-sz   await r_await w_await  svctm  %util
xvdf              0.00     0.00    0.00  301.00     0.00 13225.60    87.88   129.36  422.97    0.00  422.97   3.32  99.84

IO characteristics 在 aws 上说每个 IOPS 需要 256KiB 或更少的请求,那么 postgres 是否使用更小的数据块回写导致更多的 IOPS 请求?

虽然我有另一个 ec2 实例(比如 S2),容量为 100GB(现在 95% 已满),postgres 数据位于根卷上,并且性能很好。因此,我确信音量的大小在这里无关紧要。

受影响的 S1 卷仅存储 postgres 数据,我仍然可以通过 iostat 看到以下统计信息。不知道为什么统计数据是这样的,以及我如何在不增加卷大小的情况下减少 postgres 命令时间。 (同时所有操作 3GB 内存始终可用)

Device:         rrqm/s   wrqm/s     r/s     w/s    rkB/s    wkB/s avgrq-sz avgqu-sz   await r_await w_await  svctm  %util
xvdf              0.34     2.29    1.23  298.93    20.10 13079.03    87.28    26.19   87.26   66.96   87.34   3.29  98.78

Device:         rrqm/s   wrqm/s     r/s     w/s    rkB/s    wkB/s avgrq-sz avgqu-sz   await r_await w_await  svctm  %util
xvdf              0.00     2.40    0.60  299.00     4.80 13020.80    86.95   132.22  434.48  108.00  435.14   3.34 100.00

Device:         rrqm/s   wrqm/s     r/s     w/s    rkB/s    wkB/s avgrq-sz avgqu-sz   await r_await w_await  svctm  %util
xvdf              0.00     3.20    4.40  295.20    43.20 12866.40    86.18   122.18  417.09  142.00  421.20   3.34 100.00

Device:         rrqm/s   wrqm/s     r/s     w/s    rkB/s    wkB/s avgrq-sz avgqu-sz   await r_await w_await  svctm  %util
xvdf              0.00     2.80    2.40  297.20    23.20 12940.00    86.54   122.70  401.11  124.00  403.34   3.34  99.92

Device:         rrqm/s   wrqm/s     r/s     w/s    rkB/s    wkB/s avgrq-sz avgqu-sz   await r_await w_await  svctm  %util
xvdf              0.00     3.40    4.80  294.80    46.40 12840.00    86.02   127.43  433.15  161.67  437.57   3.34  99.92

注意:受影响的 postgres 卷包含 100 个不同的 postgres 数据库,平均大小为 110 MB/db(但老实说,我不认为这在任何情况下都是问题)

所以这个问题终于解决了。并发现它是 postgres statistics collector,它在后台 运行 并发出许多小的(小于 256 KB)io 请求(因为我们有 100+ dbs)耗尽了 100GB 的所有 300 IOPS磁盘。结果,所有 postgres 操作都排在队列中,并且需要花费大量时间来处理。

Postgres 文档说

The statistics collector transmits the collected information to backends (including autovacuum) through temporary files. These files are stored in the pg_stat_tmp subdirectory. When the postmaster shuts down, a permanent copy of the statistics data is stored in the global subdirectory. For increased performance, the parameter stats_temp_directory can be pointed at a RAM-based file system, decreasing physical I/O requirements.

我通过在 tmpfs 文件系统中挂载 pg_stats_tmp 将 pg_stats_tmp 文件指向 ram 而不是磁盘。这个 blog 解释了如何一步一步地做到这一点。