왜 파일 I / O없이 Postgres가 95 %의 유휴 상태입니까?


8

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 초가 걸립니다. 공간 인덱스가 중요합니다! :)


이 항목이 상당히 오래되었지만 비슷한 문제가 발생한다는 것을 알고 있습니다. 인덱스가 이미 존재하기 때문에 planet_osm_polygon_point를 두 번 만들 수 없습니다. 그러나 인덱스가 무엇인지 실제로 중요하지 않습니다.
Sebastian Borggrewe

색인이 존재하면 왜 다른 색인을 작성 하시겠습니까? 그러나 어쨌든 이전 항목을 삭제하거나 새 이름을 바꿀 수 있습니다.
Steve Bennett

방금 두 인덱스 이후에 묻습니다. gist (way)를 사용하여 planet_osm_polygon에 인덱스 planet_osm_polygon_point를 만듭니다. gist (way)를 사용하여 planet_osm_point에 인덱스 planet_osm_polygon_point를 작성하십시오. 이름이 planet_osm_polygon_point인데, 뭔가 빠지지 않는 한 실수처럼 보입니다.
Sebastian Borggrewe

오! 나는 이해하지 못했다. 예, 대답에 오타가 있습니다.
Steve Bennett

감사합니다 Steve, 나중에 참조 할 수 있도록 오타를 수정할 수 있습니까? 감사.
Sebastian Borggrewe

답변:


4

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

Seq Scan on planet_osm_polygon p 

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

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


이것을 지적 해 주셔서 감사합니다-나는 그것을 놓쳤다. 이 테이블에는 실제로 두 개의 인덱스가 있습니다. 더 많은 정보로 내 질문을 업데이트합니다.
Steve Bennett

아-그 링크에 답이 있습니다. 예. "인덱스"가 있었지만 실제 지오메트리 필드 ( "way")가 아닌 ID 필드에 있었기 때문에 공간 인덱싱에는 쓸모가 없습니다. 프레드릭의 의견에는 답변이 포함되어 있습니다.
스티브 베넷

4

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약간의 출력을 수집하여 실제로 수행중인 작업을 확인하십시오.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.