web-dev-qa-db-ja.com

ファイルI / OなしでPostgresが95%アイドル状態になっているのはなぜですか?

TileMill/PostGISスタックを8コアのUbuntu12.04 VM OpenStackクラウドで実行しています。これは非常に類似したハードウェア(同じクラウドですが、同じクラウドですが)で正常に実行されていた非常に類似したシステムの再構築です。異なる物理ハードウェアだと思います)先週、私は(私が構築したいくつかのスクリプトを使用して)スタックをまったく同じように再構築しようとしました。

すべてが実行されますが、データベースは非常にゆっくりとクエリを実行しているため、最終的にはタイルの生成が非常に遅くなります。以前は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

(私はこのクエリを症状として含めていますが、直接解決すべき問題ではありません。この特定のクエリは週に1回程度しか実行されません。)

サーバーには32 GBのRAMが搭載されており、Postgresを次のように構成しました(Webにあるアドバイスに従ってください)。

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) 。

この特定のクエリは、この理由からおそらく適切なサンプルではないことがわかりました。使用できるコアは1つだけで、updateです(タイルレンダリングはselectsです)。

また、explainで、明らかにplanet_osm_polygonがインデックスを使用していないことに気づきませんでした。それが原因かもしれないので、次にそれを追いかけます。

Update2

問題は、間違いなく、planet_osm_polygonインデックスが使用されていることです。 2つあります(1つはosm2pgsqlで作成され、1つはランダムなガイドに従って私が作成しました)。

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秒かかります。 空間インデックスは重要です!:)

8
Steve Bennett

Explain.depesz.comによるExlay Anlayzeの出力 を実行すると、速度の大部分がこのアクションに起因することがわかります。

Seq Scan on planet_osm_polygon p 

それは以前に索引付けされましたか?今すぐインデックスを作成できますか?

その問題領域を検索したところ、Open Street Mapサイトで関連するQ&Aも見つかりました。

4
Mark Stosberg

PostgreSQLは、特定のクエリに対して1つのコアのみを使用できます。多くの同時クエリで優れた並列パフォーマンスを実現しますが、非常に大きなクエリが2、3個あるワークロードのコア数が多いというメリットはありません。したがって、単一のクエリのみを実行している場合、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出力を少し収集して、実際に何が行われているかを確認する必要があります。

4
Craig Ringer