(この記事ではPostgreSQL 10のNouveaulitésde PostgreSQL 10の例と説明を使用しました。
もちろん、PostgreSQLの第11バージョンが待機するのをすでに待っています。 しかし、バージョン10では、かなり抜本的なパフォーマンスの改善がすでに現れていることが明らかになりました。最初に対処することは間違いなく理にかなっています。
「数十」のパフォーマンスは、一度にいくつかの方向で改善されました。 この記事では、次の理由により加速に焦点を当てます。
- スキャンテーブルとインデックスの並列化、
- より効率的な集約、
- クイック遷移表
- 複数列の統計によるクエリの高速化。
並行性から始めます。
PostgreSQL 10の同時実行性
バージョン9.6では、シーケンシャルテーブルの読み取り、結合、および集計の並列化はすでに機能していました。 これは読み取り要求に関するもので、書き込み要求ではありません。 INSERT
/ UPDATE
/ DELETE
も、CTEクエリ(共通テーブル式、一般テーブル式)の作成も、操作( CREATE INDEX
、 VACUUM
、 ANALYZE
)の提供も、並列化をサポートしていませんでした。
バージョン10では、並列化が可能になります。
- 索引スキャン(
Index Scan
およびIndex Only Scan
) Merge Join
- 並べ替え順序を維持しながら結果を
Gather Merge
する( Gather Merge
) - 準備されたリクエストの実行
- 非相関サブクエリの実行
Merge Join
、左右のテーブルが順序付けられてから、並行して比較されます。
バージョン9.6で導入されたGather
Planノードは、すべてのバックグラウンドプロセスの結果をランダムな順序で収集します。 Gather Merge
は、すべてのバックグラウンドプロセスがソートされた結果を返す場合に適用されます。 ノードは順序を維持します。
並行性の詳細については、 Robert Haasの Parallel Query v2を参照してください。
パラメータ
したがって、パラメーターはpostgresql.configに現れました。
min_parallel_table_scan_size
は、スキャンを並列化する可能性が考慮されるテーブルデータの最小量を定義します。
min_parallel_index_scan_size
は、インデックスデータの最小量を定義します。これを超えると、スキャンを並列化する可能性を考慮することができます。
max_parallel_workers
は、DBMSが並列要求の処理に割り当てることができるバックグラウンドプロセスの最大数を定義します。 デフォルトでは、このパラメーターは8です。
このパラメーターを増減するときは、 max_parallel_workers_per_gather
パラメーターを考慮することを忘れないでください
max_parallel_workers_per_gather
は、単一のGatherプランノードに割り当てることができる並列プロセスの最大数を定義します。 デフォルトでは、パラメーターは2です。値0は、クエリの並列処理を無効にします。
準備する
PostgreSQL 10でテーブルt1
を作成します。
habr_10=
max_parallel_workers_per_gather
パラメーターを変更します。
postgres=
PostgreSQL 9.6でも同じことを繰り返します。
並列ビットマップヒープスキャン
PostgreSQL 9.6では、読み取り時にparallel sequential scan
テーブルスキャン( parallel sequential scan
)のみをparallel sequential scan
できましたが、インデックスアクセスはできませんでした。 スケジューラは、並列化とインデックス使用のどちらかを選択する必要がありました。
parallel bitmap heap scan
はPostgreSQL 10で使用できるため、スキャンプロセスは、読み込むデータページを示すメモリ内データ構造を作成します。 バックグラウンドプロセスは、ページの一部を並行して読み取ることができます。
habr_9_6=
habr_10=
パラレルインデックスのみのスキャンとパラレルインデックススキャン
並列インデックスのみスキャン
インデックススキャンを並行して実行できるようになりました。 Gather
ノードの存在に注意して、次のクエリによって返される実行計画を検討してください。
habr_9_6=
habr_10=
並列インデックススキャン
次に、このクエリによって返される実行計画を検討します。
habr_9_6=
habr_10=
バックグラウンドプロセスの監視
この章はPostgreSQLの高速化には直接適用されませんが、新しい並列化機能に並列プロセスを監視する新しい手段が追加されたため、ここでは関連があります。
バージョン10では、バージョン9.6と同様に、1つのセッションでリクエストを実行することにより、 pg_stat_activity
を使用して他のセッションのバックグラウンドプロセスによって処理されたリクエストのテキストを読み取ることができpg_stat_activity
。
habr_9_6=
10-kでは、プロセスタイプ( backend_type
)が表示されますが、その中にはバックグラウンドプロセスがあります。 さらに、 state
フィールドはWHERE state='active'
がアクティブなプロセスのみを残すのに役立ちます。
habr_10=
WHERE state='active'
がない場合、 walwriter
やcheckpointer
などのサービスプロセスも表示され、リクエスト中は非アクティブであることがwalwriter
ました。
-[ RECORD 1 ]
総利益
スペースを節約するために、複数のテーブルを含むOrdersのデータベースを作成するためのコードは提供しません。 以下は、異なるグループ化セットでGROUP BY
を使用したクエリの例です。
EXPLAIN (ANALYZE, BUFFERS, COSTS off) SELECT GROUPING(client_type, country_code)::bit(2), GROUPING(client_type)::boolean g_type_cli, GROUPING(country_code)::boolean g_code_pays, cl.client_type, co.country_code, SUM(l.price*l.quantity) AS topay FROM orders c JOIN order_lines l ON (c.order_number = l.order_number) JOIN clients cl ON (c.client.id = cl.client_id) JOIN contacts co ON (cl.contact_id = co.contact_id) WHERE c.order_date BETWEEN '2014-01-01' AND '2014-12-31' GROUP BY CUBE (cl.client_type, co.country_code);
9.6と10ではクエリの処理が異なりますGroupAggregate
では、 GroupAggregate
プランノードがGroupAggregate
ます。
QUERY PLAN
PostgreSQL 10では、ご覧のMixedAggregate
、 MixedAggregate
プランノードが表示されます。つまり、ハッシュとソートを使用してGROUPING SETS
(グループ化セット)を実行する機能です。 MixedAggregate
を使用すると、クエリの実行が半分になります。
QUERY PLAN
遷移表
トリガーがオペレーターレベルで機能する場合、 OLD
とNEW
は1行にのみ適用されるため使用できません。 この場合、SQL標準は遷移テーブルを提供します。
バージョン10では、SQL標準に基づいてこの問題を解決できます。
以下に使用例を示します。
トリガーを持つメインテーブルと、メインから削除されたレコードを保存するアーカイブテーブルを作成します。
habr_10=
次に、ストアドプロシージャのコードを作成する必要があります。
habr_10=
メインテーブルにトリガーを追加します。
habr_10=
100万行を挿入して削除します。 EXPLAIN ANALYZE
をEXPLAIN ANALYZE
、行を削除する時間とトリガーの時間を調べることができます。
habr_10=
行の削除には約1.5秒かかりますが、トリガーは2.5秒かかります。
比較のために、これが以前に行われた方法です(トリガーを行レベルで構成):
habr_9_6=
行レベルの操作モードでは、トリガーが10.7秒で100万行を削除し、そのうち8.6がトリガーされることがわかります。 トリガーがオペレーターレベルで動作すると、4秒が取得され、そのうち1.5秒がトリガーの動作に費やされます。 つまり、遷移表は生産性を向上させることができます。
遷移表への大きな関心はこれに関連しています。
このトピックの詳細については、次をご覧ください。
複数列の統計
これで、同じテーブルの複数の列の統計を作成できます。 このため、列が強く相関している場合、実行計画の準備で推定を改善することができます。
例:
habr_10=
データの分散は非常に簡単です。テーブル全体に均等に分散される値は100のみです。
列a
:
habr_10=
オプティマイザーは条件をチェックし、この条件の選択性は1%(行=挿入された10,000個のレコードのうち100個)であると結論付けます。
同様に、列b
推定値を取得します。
次に、 AND
を使用して各列に同じ条件を適用します。
habr_10=
オプティマイザーは各条件の選択性を個別に推定し、上記と同じ1%の推定値を受け取ります。 選択性の最終評価では、固有値の0.01%が得られます。つまり、非常に大幅に過小評価されます( cost
とactual
値の大きな差)。
スコアを改善するために、複数列の統計を作成できるようになりました。
habr_10=
今確認してください:
habr_10=
これで評価は適切です。
詳細については、 多変量n固有係数の実装ページを参照してください。
続く