web-dev-qa-db-ja.com

PostgreSQL:なぜCREATE TABLE ASはCREATE ... INSERT INTOより速いのですか?

以下は、同じものの2つの異なる構文です。

  1. COPY TABLE AS SELECTCTAS)を使用します。

    CREATE TABLE main
    AS
      SELECT *
      FROM other;
    
  2. CREATE TABLEおよびINSERT INTOを使用した個別のステートメントとして

    CREATE TABLE main (like other);
    
    INSERT INTO main
    SELECT *
    FROM other;
    

CTASは個別のCREATE TABLE .. INSERTよりも高速であることを確認しました。最初の実行が完了するまで20秒かかります。 2番目の構文2では、実行が完了するまでに1分15秒かかります。

違いの理由は何でしょうか?

3
user2274074

CREATE TABLE ASには、他の形式、つまり WALの削減または削除 に比べていくつかの利点があります。確かに最適化は、特定のwalのいくつかのコマンド(つまり、CREATE TABLE ASCREATE INDEXCLUSTERCOPY intoテーブルが同じトランザクションで作成または切り捨てられた)に適用できます。 -削減モード(最小)。

最小レベルでは、一部の一括操作のWALロギングを安全にスキップできるため、これらの操作を大幅に高速化できます(セクション14.4.7を参照)。

ただし、最小限のWALには、ベースバックアップとWALログからデータを再構築するための十分な情報が含まれていないため、WALアーカイブ(archive_mode)とストリーミングレプリケーションを有効にするには、レプリカ以上を使用する必要があります。

あなたはすることができます これについての詳細はここを読んでください

14.4.7。 WALアーカイブとストリーミングレプリケーションを無効にする

WALアーカイブまたはストリーミングレプリケーションを使用するインストールに大量のデータをロードする場合、大量の増分WALデータを処理するよりも、ロードの完了後に新しい基本バックアップを作成する方が速い場合があります。 ロード中の増分WALロギングを防ぐには、wal_levelを最小に、archive_modeをオフに、max_wal_sendersをゼロに設定して、アーカイブおよびストリーミングレプリケーションを無効にします。ただし、これらの設定を変更すると、サーバーの再起動が必要になることに注意してください。

アーカイバーまたはWAL送信者がWALデータを処理する時間を回避するだけでなく、実際にこれを行うと、特定のコマンドが高速になります。これは、wal_levelが最小の場合、WALをまったく書き込まないように設計されているためです。 (彼らは、WALを書くよりも、最後にfsyncを行うことで、より安全にクラッシュの安全性を保証できます。)

特記事項として、

CREATE TABLE t1 (like t2);

そして代わりに

CREATE TABLE UNLOGGED t1 (like t2);

それはさらに速くなります。ただし、WALが見つからないため、これを行わないでください。これについての詳細は

3
Evan Carroll