ファイル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

(私はこのクエリを症状として含めています。直接解決すべき問題ではありません。この特定のクエリは、週に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に移動しましたが、もちろん違いはありませんでした。

だから私は途方に暮れています。I / Oを待機していないのに、Postgresが使用可能なCPUの5%しか使用しないのはなぜですか?さらなる調査のための提案、他のツール、試してみるランダムなことを歓迎します。

更新

サーバーのスナップショットを作成し、同じクラウドの別の部分(別のアベイラビリティーゾーン)でサーバーを起動しました。結果は少し変でした。vmstatこのサーバーでは、12%のCPU使用率(8コアVMでの単一のPostgresクエリの期待値として理解しています)を報告します-実際のクエリ実行時間は実質的に同じです(630秒vs 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は1574回planet_osm_polygonを検索しましたが、実際には何も見つからなかったため、途方もなく多数のブルートフォース検索を実行しました。

新しい質問:なぜですか?

謎解き

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を2回作成することはできません。しかし、インデックスが何と呼ばれるかは重要ではありませんよね?
Sebastian Borggrewe 2016年

さて、インデックスが存在する場合、なぜ別のものを作成するのですか?ただし、いずれにしても、古いものを削除したり、新しい名前を変更したりできます。
Steve Bennett、

両方のインデックスがあるので、私はただ尋ねています。gist(way)を使用して、planet_osm_pointにインデックスplanet_osm_polygon_pointを作成します。は、planet_osm_polygon_pointという名前です。これは、何かを見落とさない限り、間違いのようです。
Sebastian Borggrewe 2016年

ああ!分かりませんでした。はい、私の回答にはタイプミスがあります。
Steve Bennett、

スティーブに感謝します。また、将来の参考のために、回答のタイプミスを訂正していただけますか。ありがとう。
Sebastian Borggrewe 2016年

回答:


4

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

Seq Scan on planet_osm_polygon p 

それは以前に索引付けされましたか?今すぐ索引付けできますか?

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


これを指摘してくれてありがとう-私はそれを逃した。このテーブルには、実際には2つのインデックスがあります。詳細情報で質問を更新しています。
スティーブベネット

ああ-そのリンクには答えがありました。はい、「インデックス」はありましたが、実際のジオメトリフィールド(「ウェイ」)ではなく、IDフィールドのみにありました-空間インデックスには役に立ちません。フレデリクのコメントには答えが含まれていた。
スティーブベネット

4

PostgreSQLは、任意のクエリに対して1つのコアのみを使用できます。多くの同時クエリで優れた並列パフォーマンスを実現しますが、非常に大きなクエリの数だけのワークロードのコア数が多くてもメリットはありません。したがって、1つのクエリのみを実行している場合、8コアシステムでは5%でもそれほど驚くことではありませんが、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.