왜 파일 I / O없이 Postgres가 95 %의 유휴 상태입니까? Filter: ((amenity = ‘pub’::text) AND (way

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

(이 쿼리를 증상으로 포함시키고 있으며 직접 해결할 문제는 없습니다.이 특정 쿼리는 일주일에 한 번 정도만 실행됩니다.)

서버에는 32GB의 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를 기다리지 않을 때 사용 가능한 CPU의 5 % 만 사용하는 이유는 무엇입니까? 추가 조사, 기타 도구, 무작위로 시도 할 수있는 제안을 환영합니다.

최신 정보

서버를 스냅 샷하여 동일한 클라우드의 다른 부분 (다른 가용 영역)에서 시작했습니다. 결과는 약간 이상했습니다. vmstat이 서버에서 12 %의 CPU 사용량 (이제 8 코어 VM에서 단일 Postgres 쿼리의 예상 값으로 이해 됨)을보고합니다. 실제 쿼리 실행 시간은 사실상 동일하지만 (630 초 대 623).

나는이 특정 쿼리가 아마도 이런 이유로 좋은 샘플이 아니라는 것을 깨달았습니다. 하나의 코어 만 사용할 수 update있으며 타일 렌더링은 단지 selects입니다.

또한 색인을 사용하지 않는 explain것으로 나타났습니다 planet_osm_polygon. 그 원인이 될 수 있으므로 다음에 추격하겠습니다.

업데이트 2

문제는 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의 답변 덕분에 대답은 매우 간단합니다. 어떤 이유로 공간 인덱스가 없었습니다. 그것들을 재생시키는 것은 사소한 일이었습니다.

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.depesz.com을 통해 Explain Anlayze 출력을 실행 하면 대부분의 속도 저하가이 조치에서 비롯된 것입니다.

Seq Scan on planet_osm_polygon p

이전에 색인이 생성 되었습니까? 지금 색인을 생성 할 수 있습니까?

해당 문제 영역을 검색하여 Open Street Map 사이트에서 관련 Q & A를 찾았습니다.


답변

PostgreSQL은 주어진 쿼리마다 하나의 코어 만 사용할 수 있습니다. 많은 동시 쿼리로 우수한 병렬 성능을 달성하지만 몇 개의 매우 큰 쿼리의 워크로드에 대해서는 큰 코어 수의 이점을 얻지 못합니다. 따라서 단일 쿼리 만 실행하는 경우 5 %가 놀라운 것은 아니지만 8 코어 시스템에서는 12 %가 될 것으로 예상합니다.

iowait가 없으면 디스크 I / O에 어려움이 없을 것입니다.

따라서 CPU 또는 I / O에서 병목 현상이 나타나지 않습니다.

쿼리가 잠금에 의해 한동안 단순히 차단 될 수 있습니까? 확인 pg_stat_activity쿼리와 함께 가입 pg_locks어떤 않은 부여 잠금 장치가 있는지. (Pg 잠금 모니터링에 대한 미리 준비된 쿼리가 있습니다).

다음으로해야 할 일은 하위 시스템 테스트를 수행하는 것입니다. 를 실행 pg_test_fsync하고 sysbench의 CPU 및 I / O 테스트 등을 사용하십시오. 이러한 테스트가 제대로 수행되지 않으면 호스팅 제공 업체에 문의하십시오.

또한 perf top -a약간의 출력을 수집하여 실제로 수행중인 작업을 확인하십시오.