web-dev-qa-db-ja.com

Postgresは大きなテーブルのインデックス作成を高速化します

20億以上のエントリ(1.5TB)を持つ大規模なPostgresテーブルと、ほとんどがnull以外のchar var列があります。挿入を高速化するために、一括アップロードする前にインデックスを削除しました。ただし、bツリーインデックスが作成されるまでには、時間がかかります。私が短縮した実行の1つでは、インデックスの作成に12時間以上かかっていました。

私が作成しようとしているサンプルのテーブルとインデックス:

        Column         |            Type             | Modifiers 
-----------------------+-----------------------------+-----------
 name                  | character varying           | not null
 id                    | character varying           | 
 lifecycle_id          | character varying           | 
 dt                    | character varying           | 
 address               | character varying           | 
 ...

Indexes: 
"name_idx" PRIMARY KEY, btree (name)

"id_idx" btree (rec_id)

"lifecycle_id_idx" btree (lifecycle_id)

実際のテーブルには18列あります。 maintenance_work_memを15GBに設定しました。これは、RDSのPostgres 9.6.11で実行されています。インスタンスクラスはdb.m4.4xlargeです。

インデックスが3つあるため、挿入する前にデータを並べ替えることは困難です。インデックスを削除せずにデータを挿入する方が速いでしょうか?インデックス作成を高速化するための他の提案はありますか?

3
Amy

PostgreSQLでは、バージョン10で単一のインデックスビルドを並列化する機能が追加されたため、この機能を利用するためのアップグレードを検討できます。

現在使用しているバージョンでも、同じテーブルに複数のインデックスを同時に作成できます(異なるデータベース接続を使用してそれぞれを呼び出す)。これにより、ある程度の非公式な並列化を実行できます。これは、インデックスの構築中にテーブルへの変更をロックアウトする通常のインデックス構築でのみ実行できます。 「同時に」インデックスビルドを使用すると、UPDATE/INSERT/DELETEをインデックスビルドと同時に実行できますが、同じテーブルでのインデックスビルドを同時に実行することはできません。

私の経験では、AWSの仮想CPUは実質的に役に立ちません。 db.m4.4xlargeは16個のvCPUを報告しますが、8個を超えて並列化する意味はありません。並列処理(v10単一インデックス、または同時に複数のインデックスを構築するだけ)を利用したい場合は、おそらくより小さな15GBを超えるMaintenance_work_memの値。

インデックスを削除せずにデータを挿入する方が速いでしょうか?

ある時点で、間違いなく。これは、一括挿入に含まれるレコードの数とその他の多くの要素に依存し、それについて考えるだけでは答えられません。実験的な質問です。

3
jjanes

インデックスを作成するための最適なチューニング方法は、maintenance_work_memの非常に高い値です。

1.5 TBテーブルに数百万行を追加するだけの場合、インデックスの削除と再作成はおそらく遅くなります。テストが実行されて、どこから高速になるかを判断する必要があります。

3
Laurenz Albe

この質問を投稿する前に、2つのテストを実行していましたが、終了するかどうかはわかりませんでした。彼らが終わっていない場合にスピードを上げる方法についての洞察を得ることを望んでいました。ありがたいことに、テストの1つは終了しました。また、jjanesが投稿した提案を試したところ、良い結果が得られました。

Postgres 9を使用して、2つのテストを実行しました。

  • インデックス付きの20億のエントリの挿入
  • すでに20億のエントリが挿入されているテーブルのインデックスの作成

最初のテストは1週間実行され、20億エントリの20%しか挿入されていません。インデックスを使用して挿入することは、間違いなく方法ではありません。

2番目のテストには45時間かかりました。インデックスの作成にかかる時間を知らなかったため、以前のテストの一部を途中で終了し、それらが完全に実行されることを確認できませんでした。長い時間がかかりますが、今のところ、永遠に実行されないことが嬉しいです。

Jjanesの提案に従って、Postgres 11にアップグレードし、パラレルワーカーを8に設定し、メンテナンスワークメモリを7GBに設定しました。このガイドに従ってパラメーターを選択しました: https://www.cybertec-postgresql.com/en/postgresql-parallel-create-index-for-better-performance/ 。これにより、インデックスの作成が高速化され、35時間しかかかりませんでした。 10時間を剃ることは素晴らしい驚きでした。ありがとう!

3
Amy