性能 – 为什么Postgres闲置95%,没有文件I / O?

我在OpenStack云上的8核Ubuntu 12.04 VM上运行了TileMill / PostGIS堆栈.这是一个非常相似的系统的重建,上周在非常相似的硬件(相同的云,但不同的物理硬件,我相信)上运行良好.我试图重建堆栈完全相同(使用我已经构建的一些脚本).

一切都在运行,但数据库正在缓慢地执行查询,这最终表现为非常慢的瓦片生成.一个示例查询(计算澳大利亚每个城镇半径范围内的酒吧数量),之前花了10-20秒,现在花了10多分钟:

explain (analyze, buffers) update places set pubs = 
(select count(*) from planet_osm_point p where p.amenity = 'pub' and st_dwithin(p.way,places.way,scope)) +
(select count(*) from planet_osm_polygon p where p.amenity = 'pub' and st_dwithin(p.way,places.way,scope)) ;
 Update on places  (cost=0.00..948254806.93 rows=9037 width=160) (actual time=623321.558..623321.558 rows=0 loops=1)
   Buffers: shared hit=132126300
   ->  Seq Scan on places  (cost=0.00..948254806.93 rows=9037 width=160) (actual time=68.130..622931.130 rows=9037 loops=1)
         Buffers: shared hit=132107781
         SubPlan 1
           ->  Aggregate  (cost=12.95..12.96 rows=1 width=0) (actual time=0.187..0.188 rows=1 loops=9037)
                 Buffers: shared hit=158171
                 ->  Index Scan using planet_osm_point_index on planet_osm_point p  (cost=0.00..12.94 rows=1 width=0) (actual time=0.163..0.179 rows=0 loops=9037)
                       Index Cond: (way && st_expand(places.way, (places.scope)::double precision))
                       Filter: ((amenity = 'pub'::text) AND (places.way && st_expand(way, (places.scope)::double precision)) AND _st_dwithin(way, places.way, (places.scope)::double precision))
                       Buffers: shared hit=158171
         SubPlan 2
           ->  Aggregate  (cost=104917.24..104917.25 rows=1 width=0) (actual time=68.727..68.728 rows=1 loops=9037)
                 Buffers: shared hit=131949237
                 ->  Seq Scan on planet_osm_polygon p  (cost=0.00..104917.24 rows=1 width=0) (actual time=68.138..68.716 rows=0 loops=9037)
                       Filter: ((amenity = 'pub'::text) AND (way && st_expand(places.way, (places.scope)::double precision)) AND (places.way && st_expand(way, (places.scope)::double precision)) AND _st_dwithin(way, places.way, (places.scope)::double precision))
                       Buffers: shared hit=131949237
 Total runtime: 623321.801 ms

(我将此查询作为症状包括在内,而不是直接解决的问题.此特定查询每周只运行一次.)

服务器有32 GB的RAM,我按如下方式配置了Postgres(遵循网上的建议):

shared_buffers = 8GB
autovacuum = on
effective_cache_size = 8GB
work_mem = 128MB
maintenance_work_mem = 64MB
wal_buffers = 1MB
checkpoint_segments = 10

iostat显示没有被读取,写入一些数据(不知道在哪里或为什么),以及95%空闲CPU:

avg-cpu:  %user   %nice %system %iowait  %steal   %idle
           5.40    0.00    0.00    0.11    0.00   94.49

Device:            tps    kB_read/s    kB_wrtn/s    kB_read    kB_wrtn
vda               0.20         0.00         0.80          0          8
vdb               2.30         0.00        17.58          0        176

vmstat的示例输出:

  procs -----------memory---------- ---swap-- -----io---- -system-- ----cpu----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa
...
 1  0      0 18329748 126108 12600436    0    0     0    18  148  140  5  0 95  0
 2  0      0 18329400 126124 12600436    0    0     0     9  173  228  5  0 95  0

抓住吸管,我将Postgres数据目录从vda移动到了vdb,但当然没有区别.

所以我很茫然.为什么Postgres在不等待任何I / O时只使用5%的可用CPU?我欢迎任何进一步调查的建议,其他工具,随机的尝试.

更新

我将服务器快照并在同一个云的不同部分(不同的可用区域)上启动它.结果有点奇怪.此服务器上的vmstat报告12%的CPU使用率(我现在将其理解为8核VM上单个Postgres查询的预期值) – 尽管实际查询执行时间几乎相同(630秒对623).

我现在意识到,由于这个原因,这个特定的查询可能不是一个好的示例:它只能使用一个核心,而且它是一个更新(而瓦片渲染只是选择).

我在解释中也没有注意到,planet_osm_polygon显然没有使用索引.这很可能是原因,所以接下来我会追逐.

UPDATE2

问题肯定似乎是没有使用planet_osm_polygon索引.有两个(一个由osm2pgsql创建,一个由我创建,遵循一些随机指南):

CREATE INDEX idx_planet_osm_polygon_tags
  ON planet_osm_polygon
  USING gist
  (tags);


CREATE INDEX planet_osm_polygon_pkey
  ON planet_osm_polygon
  USING btree
  (osm_id);

我认为,planet_osm_polygon和planet_osm_point的统计数据非常具有启发性:

planet_osm_polygon:

Sequential Scans    194204  
Sequential Tuples Read  60981018608 
Index Scans 1574    
Index Tuples Fetched    0

planet_osm_point:

Sequential Scans    1142    
Sequential Tuples Read  12960604    
Index Scans 183454  
Index Tuples Fetched    43427685

如果我读得对,Postgres已经搜索了planet_osm_polygon 1574次,但实际上从未找到任何东西,所以进行了大量的暴力搜索.

新问题:为什么?

谜团已揭开

感谢Frederik Ramm’s answer,答案结果相当简单:由于某种原因,没有空间索引.重生它们是微不足道的:

create index planet_osm_polygon_polygon on planet_osm_polygon using gist(way);
create index planet_osm_polygon_point on planet_osm_point using gist(way);

现在运行该查询需要4.6秒.空间索引很重要! 🙂

运行Explain Anlayze output through explain.depesz.com会突出显示大部分缓慢来自此操作:

Seq Scan on planet_osm_polygon p 

那之前有索引吗?你现在可以索引吗?

通过搜索该问题区域,我还在Open Street Map网站上找到了相关的Q& A:

> Local Tile Server – EXTREMELY slow rendering

翻译自:https://serverfault.com/questions/533578/why-is-postgres-sitting-95-idle-with-no-file-i-o

转载注明原文:性能 – 为什么Postgres闲置95%,没有文件I / O?