web-dev-qa-db-ja.com

Postgres 9.0とPostgres 10および11のパフォーマンス

データベースをウェブホスティングプロバイダー(postgres 9.0)からローカルネットワークサーバー(postgres 10と最新11の両方を試してみました)に移動したいと思います。私たちのマシンはWindowsサーバーであり、データベース専用の16GB RAMの高速XEONマシンです。

しかし、default_statistics_targer = 4000を上げて統計を分析した後でも、以前は非常に高速に機能していた多くのビューを実行できません。 Webホスティングプロバイダーサーバーは微調整されており、何らかの理由で実行プランが変わっているようです。

私たちのPostgresは標準のインストール設定です。

簡略化されたクエリの例は次のとおりです(最大のテーブルは「数百万レコードの大きなデールテーブルです(外部キーとのバインディングテーブルです)」。他のテーブルははるかに小さく、1万のレコードです(システムは真空分析され、フレッシュインストールです)。

EXPLAIN ANALYZE
SELECT REKLAMACNY_LIST.ID REKLAMACNY_LIST_ID
FROM REKLAMACNY_LIST
WHERE REKLAMACNY_LIST.VALIDTO IS NULL
  AND
    ( SELECT NOT tr.typ_odstupenia::boolean
     AND sr.konecny_stav::boolean
     FROM dale d1
     CROSS JOIN typ_reklamacie tr
     CROSS JOIN dale d2
     CROSS JOIN stav_reklamacie sr
     WHERE TRUE
       AND d1.fk7 = reklamacny_list.id
       AND d2.fk7 = reklamacny_list.id
       AND d1.fk1 = tr.id
       AND d2.fk3 = sr.id
       AND sr.validto IS NULL
       AND tr.validto IS NULL
       AND d1.validto IS NULL
       AND d2.validto IS NULL )
ORDER BY reklamacny_list_id DESC
LIMIT 100

テスト用のpostgres 11サーバーの分析について説明する

"Limit  (cost=0.29..18432.84 rows=100 width=4) (actual time=11804.484..331036.595 rows=91 loops=1)"
"  ->  Index Scan Backward using reklamacny_list_pk on reklamacny_list  (cost=0.29..2578713.84 rows=13990 width=4) (actual time=11804.482..331036.524 rows=91 loops=1)"
"        Index Cond: (id > 0)"
"        Filter: ((validto IS NULL) AND (SubPlan 1))"
"        Rows Removed by Filter: 29199"
"        SubPlan 1"
"          ->  Hash Join  (cost=5.30..87.57 rows=250 width=1) (actual time=5.246..11.824 rows=1 loops=27981)"
"                Hash Cond: (d2.fk3 = sr.id)"
"                ->  Merge Join  (cost=1.85..80.76 rows=324 width=9) (actual time=5.222..11.806 rows=6 loops=27981)"
"                      Merge Cond: (d1.fk1 = tr.id)"
"                      ->  Nested Loop  (cost=0.71..25556.34 rows=324 width=8) (actual time=5.211..11.794 rows=6 loops=27981)"
"                            ->  Index Scan using dale_idx_fk1 on dale d1  (cost=0.29..25510.95 rows=18 width=4) (actual time=5.195..11.772 rows=1 loops=27981)"
"                                  Filter: (fk7 = reklamacny_list.id)"
"                                  Rows Removed by Filter: 28432"
"                            ->  Materialize  (cost=0.42..41.38 rows=18 width=4) (actual time=0.011..0.015 rows=6 loops=27890)"
"                                  ->  Index Scan using dale_fk7_idx on dale d2  (cost=0.42..41.29 rows=18 width=4) (actual time=0.007..0.010 rows=6 loops=27890)"
"                                        Index Cond: (fk7 = reklamacny_list.id)"
"                      ->  Sort  (cost=1.14..1.15 rows=6 width=9) (actual time=0.009..0.009 rows=1 loops=27890)"
"                            Sort Key: tr.id"
"                            Sort Method: quicksort  Memory: 25kB"
"                            ->  Seq Scan on typ_reklamacie tr  (cost=0.00..1.06 rows=6 width=9) (actual time=0.002..0.004 rows=6 loops=27890)"
"                                  Filter: (validto IS NULL)"
"                ->  Hash  (cost=2.74..2.74 rows=57 width=9) (actual time=0.046..0.047 rows=57 loops=1)"
"                      Buckets: 1024  Batches: 1  Memory Usage: 11kB"
"                      ->  Seq Scan on stav_reklamacie sr  (cost=0.00..2.74 rows=57 width=9) (actual time=0.012..0.030 rows=57 loops=1)"
"                            Filter: (validto IS NULL)"
"                            Rows Removed by Filter: 17"
"Planning Time: 10.174 ms"
"Execution Time: 331036.893 ms"

私たちのテストpostgres 10.0での実行には、永久的な結果と即時の結果が必要です

"Limit  (cost=0.29..163635.75 rows=100 width=4) (actual time=24.199..925.691 rows=70 loops=1)"
"  ->  Index Scan Backward using reklamacny_list_pk on reklamacny_list  (cost=0.29..21326610.37 rows=13033 width=4) (actual time=24.195..925.660 rows=70 loops=1)"
"        Index Cond: (id > 0)"
"        Filter: ((validto IS NULL) AND (SubPlan 1))"
"        Rows Removed by Filter: 27218"
"        SubPlan 1"
"          ->  Nested Loop  (cost=4.22..781.03 rows=1293 width=1) (actual time=0.018..0.034 rows=1 loops=26066)"
"                ->  Hash Join  (cost=3.80..377.12 rows=76 width=5) (actual time=0.005..0.005 rows=1 loops=26066)"
"                      Hash Cond: (d2.fk3 = sr.id)"
"                      ->  Index Scan using dale_fk7_idx on dale d2  (cost=0.42..372.47 rows=100 width=4) (actual time=0.002..0.004 rows=5 loops=26066)"
"                            Index Cond: (fk7 = reklamacny_list.id)"
"                      ->  Hash  (cost=2.71..2.71 rows=54 width=9) (actual time=0.049..0.049 rows=54 loops=1)"
"                            Buckets: 1024  Batches: 1  Memory Usage: 11kB"
"                            ->  Seq Scan on stav_reklamacie sr  (cost=0.00..2.71 rows=54 width=9) (actual time=0.016..0.032 rows=54 loops=1)"
"                                  Filter: (validto IS NULL)"
"                                  Rows Removed by Filter: 17"
"                ->  Materialize  (cost=0.42..374.87 rows=17 width=24) (actual time=0.013..0.027 rows=1 loops=25987)"
"                      ->  Nested Loop  (cost=0.42..374.78 rows=17 width=24) (actual time=0.010..0.024 rows=1 loops=25987)"
"                            Join Filter: (d1.fk1 = tr.id)"
"                            Rows Removed by Join Filter: 32"
"                            ->  Seq Scan on typ_reklamacie tr  (cost=0.00..1.06 rows=1 width=28) (actual time=0.001..0.002 rows=6 loops=25987)"
"                                  Filter: (validto IS NULL)"
"                            ->  Index Scan using dale_fk7_idx on dale d1  (cost=0.42..372.47 rows=100 width=4) (actual time=0.002..0.003 rows=5 loops=155922)"
"                                  Index Cond: (fk7 = reklamacny_list.id)"
"Planning time: 8.460 ms"
"Execution time: 925.870 ms"

これはほんの一例です。しかし、ほとんどすべてのクエリは単に11で何倍も遅くなり、10でも永遠にかかるものでさえ、Webプロバイダーpostgres 9.0(何百もの異なるデータベースをホストしている)によって即座に返されます

調査する価値のある問題は何かある点がありますか?

一部のメモリパラメータを調整することは役立ちますか? (サーバーにはpostgresとOS専用の16GBがあり、接続しているユーザーは約50人になります)実際にdefault_statisticts_target = 10000を上げると、それでも大いに役立ちました。

合体を伴うリクエストの異なるバージョン、それ以外は同じ

EXPLAIN ANALYZE
SELECT REKLAMACNY_LIST.ID REKLAMACNY_LIST_ID
FROM REKLAMACNY_LIST
WHERE REKLAMACNY_LIST.VALIDTO IS NULL
  AND REKLAMACNY_LIST.ID > 0
  AND ((
          ( SELECT (NOT COALESCE(tr.typ_odstupenia, 'False')::boolean)
           AND COALESCE(sr.konecny_stav, 'False'):: boolean
           FROM dale d1
           CROSS JOIN typ_reklamacie tr
           CROSS JOIN dale d2
           CROSS JOIN stav_reklamacie sr
           WHERE TRUE
             AND d1.fk7 = reklamacny_list.id
             AND d2.fk7 = reklamacny_list.id
             AND d1.fk1 = tr.id
             AND d2.fk3 = sr.id
             AND sr.validto IS NULL
             AND tr.validto IS NULL
             AND d1.validto IS NULL
             AND d2.validto IS NULL )))
ORDER BY reklamacny_list_id DESC
LIMIT 100

Postgres 11では、10秒にジャンプします(前のバージョンのリクエストとの合体なしの大きな違い)

"Limit  (cost=0.29..18432.84 rows=100 width=4) (actual time=447.853..10695.583 rows=100 loops=1)"
"  ->  Index Scan Backward using reklamacny_list_pk on reklamacny_list  (cost=0.29..2578713.84 rows=13990 width=4) (actual time=447.851..10695.495 rows=100 loops=1)"
"        Index Cond: (id > 0)"
"        Filter: ((validto IS NULL) AND (SubPlan 1))"
"        Rows Removed by Filter: 687"
"        SubPlan 1"
"          ->  Hash Join  (cost=5.30..87.57 rows=250 width=1) (actual time=11.436..14.102 rows=1 loops=758)"
"                Hash Cond: (d2.fk3 = sr.id)"
"                ->  Merge Join  (cost=1.85..80.76 rows=324 width=9) (actual time=11.407..14.076 rows=5 loops=758)"
"                      Merge Cond: (d1.fk1 = tr.id)"
"                      ->  Nested Loop  (cost=0.71..25556.34 rows=324 width=8) (actual time=11.389..14.056 rows=5 loops=758)"
"                            ->  Index Scan using dale_idx_fk1 on dale d1  (cost=0.29..25510.95 rows=18 width=4) (actual time=11.361..14.023 rows=1 loops=758)"
"                                  Filter: (fk7 = reklamacny_list.id)"
"                                  Rows Removed by Filter: 28432"
"                            ->  Materialize  (cost=0.42..41.38 rows=18 width=4) (actual time=0.017..0.021 rows=5 loops=754)"
"                                  ->  Index Scan using dale_fk7_idx on dale d2  (cost=0.42..41.29 rows=18 width=4) (actual time=0.009..0.012 rows=5 loops=754)"
"                                        Index Cond: (fk7 = reklamacny_list.id)"
"                      ->  Sort  (cost=1.14..1.15 rows=6 width=9) (actual time=0.015..0.015 rows=2 loops=754)"
"                            Sort Key: tr.id"
"                            Sort Method: quicksort  Memory: 25kB"
"                            ->  Seq Scan on typ_reklamacie tr  (cost=0.00..1.06 rows=6 width=9) (actual time=0.003..0.006 rows=6 loops=754)"
"                                  Filter: (validto IS NULL)"
"                ->  Hash  (cost=2.74..2.74 rows=57 width=9) (actual time=0.092..0.092 rows=57 loops=1)"
"                      Buckets: 1024  Batches: 1  Memory Usage: 11kB"
"                      ->  Seq Scan on stav_reklamacie sr  (cost=0.00..2.74 rows=57 width=9) (actual time=0.032..0.068 rows=57 loops=1)"
"                            Filter: (validto IS NULL)"
"                            Rows Removed by Filter: 17"
"Planning Time: 1.556 ms"
"Execution Time: 10695.752 ms"

オン

postgres 10

"Limit  (cost=0.29..163635.75 rows=100 width=4) (actual time=1.958..20.024 rows=100 loops=1)"
"  ->  Index Scan Backward using reklamacny_list_pk on reklamacny_list  (cost=0.29..21326610.37 rows=13033 width=4) (actual time=1.957..20.011 rows=100 loops=1)"
"        Index Cond: (id > 0)"
"        Filter: ((validto IS NULL) AND (SubPlan 1))"
"        Rows Removed by Filter: 572"
"        SubPlan 1"
"          ->  Nested Loop  (cost=4.22..781.03 rows=1293 width=1) (actual time=0.017..0.031 rows=1 loops=609)"
"                ->  Hash Join  (cost=3.80..377.12 rows=76 width=5) (actual time=0.004..0.004 rows=1 loops=609)"
"                      Hash Cond: (d2.fk3 = sr.id)"
"                      ->  Index Scan using dale_fk7_idx on dale d2  (cost=0.42..372.47 rows=100 width=4) (actual time=0.002..0.003 rows=5 loops=609)"
"                            Index Cond: (fk7 = reklamacny_list.id)"
"                      ->  Hash  (cost=2.71..2.71 rows=54 width=9) (actual time=0.037..0.037 rows=54 loops=1)"
"                            Buckets: 1024  Batches: 1  Memory Usage: 11kB"
"                            ->  Seq Scan on stav_reklamacie sr  (cost=0.00..2.71 rows=54 width=9) (actual time=0.009..0.023 rows=54 loops=1)"
"                                  Filter: (validto IS NULL)"
"                                  Rows Removed by Filter: 17"
"                ->  Materialize  (cost=0.42..374.87 rows=17 width=24) (actual time=0.013..0.025 rows=1 loops=604)"
"                      ->  Nested Loop  (cost=0.42..374.78 rows=17 width=24) (actual time=0.010..0.022 rows=1 loops=604)"
"                            Join Filter: (d1.fk1 = tr.id)"
"                            Rows Removed by Join Filter: 31"
"                            ->  Seq Scan on typ_reklamacie tr  (cost=0.00..1.06 rows=1 width=28) (actual time=0.001..0.002 rows=6 loops=604)"
"                                  Filter: (validto IS NULL)"
"                            ->  Index Scan using dale_fk7_idx on dale d1  (cost=0.42..372.47 rows=100 width=4) (actual time=0.002..0.003 rows=5 loops=3624)"
"                                  Index Cond: (fk7 = reklamacny_list.id)"
"Planning time: 1.418 ms"
"Execution time: 20.193 ms"

Zipファイル(postgres.conf構成を含む)に完全なログを添付しています。デフォルトの統計ターゲットを上げると効果があるようですが、値が非常に高い場合のみです。
https://www.dropbox.com/s/7m3wy9nkapqitca/SpeedTest.zip?dl=

6
Martin Ritchie

デフォルトのpostgresql.conf構成は、フットプリントが小さいデータベース用であり、データベースが大きく、複雑な結合を使用してクエリを実行すると、遅くなります。

あなたのpostgresql10設定ファイルから、共有メモリが128MBにのみ設定されていることがわかりました(他の多くの設定も非常に小さいです)。これを再構成する必要があります。

PostgreSQLサーバーのチューニングは大きなトピックであり、ハードウェアの種類によって異なる設定も必要になります。これには、設定と構成を継続的に改善しながら試行錯誤が伴うものもあります。

ここでは全体の説明をすることはできませんが、以前使用していた調整された設定を提供することができます。

目標

  • 私のサーバーでは4 GB以下のメモリを使用してください(私のサーバーはPostgreSQL DBの実行専用ではないため)
  • サーバーのコア数は8以上
max_connections : 800
shared_buffers : 1536MB
work_mem : 24MB
maintenance_work_mem : 480MB
vacuum_cost_delay : 20ms
synchronous_commit : local
wal_buffers : 8MB
max_wal_size : 1536GB
checkpoint_completion_target : 0.9
effective_cache_size : 4GB
deadlock_timeout : 3s
log_min_duration_statement : 5000
log_error_verbosity : verbose
log_autovacuum_min_duration : 10000
log_lock_waits : on
5
user170807

psql 10:バッファー:共有ヒット= 4.439.193
psql 09:バッファー:共有ヒット= ____ 7.493読み取り= 686

https://www.postgresql.org/docs/11/sql-explain.html

バッファーの使用に関する情報を含めます。具体的には、ヒット、読み取り、ダーティ、書き込みされた共有ブロックの数、ヒット、読み取り、ダーティ、書き込みされたローカルブロックの数、読み取りおよび書き込みされた一時ブロックの数を含めます。ヒットとは、必要なときにブロックがすでにキャッシュ内で見つかったため、読み取りが回避されたことを意味します。共有ブロックには、通常のテーブルとインデックスからのデータが含まれています。ローカルブロックには、一時テーブルとインデックスからのデータが含まれます。一時ブロックには、ソート、ハッシュ、マテリアライズ計画ノードなどで使用される短期的な作業データが含まれています。ダーティになったブロックの数は、このクエリによって変更された、以前に変更されていないブロックの数を示します。書き込まれたブロックの数は、クエリ処理中にこのバックエンドによってキャッシュから削除された、以前にダーティにされたブロックの数を示します。上位レベルのノードに表示されるブロックの数には、そのすべての子ノードで使用されるブロックが含まれます。テキスト形式では、ゼロ以外の値のみが出力されます。このパラメーターは、ANALYZEも有効になっている場合にのみ使用できます。デフォルトはFALSEです。

p09のdbに何か問題があります。p10で約8000のバッファの関与があり、4Mのバッファヒットがあります。

同じデータセットにある場合、データベースには空の行や削除された行がたくさんあるはずです。

その場合は、掃除機が役立つはずです。


実行計画はかなり異なります。関係する行の数の見積もりは、特定の列の更新された統計が異なる場合があります。

https://www.citusdata.com/blog/2018/03/06/postgres-planner-and-its-usage-of-statistics/


psql 09プランには、個別の並べ替え部分はありません。多分インデックスは同じではありません。 psql 09はすでに正しい順序で日付を取得している可能性があります....

2
user1817599