空きディスク容量なしでVACUUM FULLを実行する必要があります


27

サーバー上のhdスペースの90%近くを占めるテーブルが1つあります。スペースを空けるために、いくつかの列をドロップすることにしました。しかし、スペースをOSに戻す必要があります。ただし、問題は、VACUUM FULLを実行し、テーブルのコピーを作成するための十分な空き領域がない場合にどうなるかわからないことです。

VACUUM FULLは使用すべきではないことを理解していますが、このシナリオでは最良の選択肢であると考えました。

任意のアイデアをいただければ幸いです。

PostgreSQL 9.0.6を使用しています

回答:


19

vacummを実行したり、再構築するのに十分なスペースがないため、postgresqlデータベースを復元することでいつでも再構築できます。データベース、テーブル、インデックスを復元すると、スペースとデフラグが解放されます。その後、自動メンテナンスを設定して、データベースを定期的に空にすることができます。

1 postgresqlサーバー上のすべてのデータベースをバックアップします

すべてのデータベースを十分なスペースのあるパーティションにバックアップする必要があります。Linuxを使用している場合は、gzipを使用してバックアップをさらに圧縮し、スペースを節約できます

su - postgres
pg_dumpall | gzip -9 > /some/partition/all.dbs.out.gz

2設定ファイルのバックアップ

cp /path/to/postgresql/data_directory/*.conf /some/partition/

3 Postgresqlを停止します

pg_ctl -D /path/to/postgresql/data_directory stop

4データディレクトリの内容を消去します

rm -Rf /path/to/postgresql/data_directory/*

5 initdbを実行してデータディレクトリを再初期化します

initdb -D /path/to/postgresql/data_directory

6構成ファイルの復元

cp /some/partition/*.conf /path/to/postgresql/data_directory/*.conf 

7 Postgresqlを起動します

pg_ctl -D /path/to/postgresql/data_directory start

8作成したすべてのデータベースのダンプを復元します

gunzip /some/partition/all.dbs.out.gz
psql -f /some/partition/all.dbs.out

1
おかげで、これが私がやったことですが、いくつか違いがあります。バックアップ後にデータベースを削除しました。次に、新しいものを作成して復元しました。
ジャスティン

どういたしまして。ただし、データディレクトリの内容を削除してinitdbを実行するだけで十分であると考えました。
クレイグエフレイン

うまくいきましgzipた。時間を節約するために、一部をスキップすることをお勧めします。
ラファエルバルボサ

17

注:9.1でこれをテストしました。ここには9.0サーバーがありません。9.0でも動作しますが、私は確信しています。


注意(@ernyのコメントに記載):

Note that high CPU load due to I/O operations may be expected.

一時表領域を使用することで、ほとんどダウンタイムなしでこれを実行できます。ダウンタイムは排他ロックの形になります。しかし、テーブルの上でのみ掃除機をかけています。そのため、クライアントクエリは、問題のテーブルにアクセスした場合にロックが取得されるのを待つだけです。既存の接続を閉じる必要はありません。

ただし、注意が必要なのは、テーブルとバキュームを完全に移動するには、排他ロックを最初に待機する必要があるということです。


まず、明らかに追加のストレージが必要です。以下のようStéphaneなコメントに言及し、このニーズは、問題のテーブルとして大きな二倍以上になるようにVACUUM FULL完全なコピーを行います。運がよく、マシンにディスクを動的に追加できる場合は、それを行います。では最悪の場合、あなただけのUSBディスク(危険なと遅いものの)を添付することができます!

次に、新しいデバイスをマウントして、テーブルスペースとして使用できるようにします。

CREATE TABLESPACE tempspace LOCATION '/path/to/new/folder';

次を使用して、表領域を簡単にリストできます。

\db

テーブルの現在のテーブルスペースを再確認します(どこに戻すかを知る必要があります)。

SELECT tablespace FROM pg_tables WHERE tablename = 'mytable';

の場合NULL、デフォルトのテーブルスペースにあります:

SHOW default_tablespace;

場合はそれがあるNULLとしても、それは可能性が高くなりますpg_default(チェック公式ドキュメント、それが変わったのケースでは)。

次に、テーブルを移動します。

ALTER TABLE mytable SET TABLESPACE tempspace;
COMMIT;  -- if autocommit is off

掃除機をかける:

VACUUM FULL mytable;

元に戻す:

-- assuming you are using the defaults, the tablespace will be "pg_default".
-- Otherwise use the value from the SELECT we did earlier.
ALTER TABLE mytable SET TABLESPACE pg_default;
COMMIT;  -- if autocommit is off

一時スペースを削除します。

DROP TABLESPACE tempspace;

NB:動きは元のデータディレクトリに多くのディスク領域を使用するように見える...
クリス・ウィザース

9.3でテストしたところ、魅力のように機能します。
Bartekヤブロンスキー

9.1の実稼働で正常に使用されました。表領域を変更すると、元の使用領域が解放されます。I / O操作による高いCPU負荷が予想されることに注意してください。
アーニー

2
すばらしいヒント、この詳細な説明に感謝します。一時テーブルスペースでは、テーブルの完全なコピーを作成しているsize of table x 2ため、少なくともが必要であることに注意しVACUUM FULLてください。
ステファン

@Stéphaneに感謝します。本体に情報を追加しました。
exhuma

2

早くて汚い:

  • Postgresを停止する
  • メインデータベースディレクトリを、掃除機をかける十分なスペースがある別のディスクに移動します。
  • メインの元の場所で、新しい場所にシンボリックリンクを追加します
  • 真空
  • シンボリックリンクを削除し、メインディレクトリを元の場所に戻します
  • Postgresを起動します

例えば、:

$ service postgresql stop $ mv /var/lib/postgresql/9.5/main /mnt/bigdisk $ ln -sr /mnt/bigdisk/main /var/lib/postgresql/9.5 $ vacuumdb --all --full $ rm /var/lib/postgresql/9.5/main $ mv /mnt/bigdisk/main /var/lib/postgresql/9.5 $ service postgresql start


0

ダンプと復元を実行するためのディスク領域がある場合、vacuumdb --fullを実行するためのディスク領域が必要です。問題は、vacuumdb --fullがデータファイル全体のコピーを作成することです。だから、あなたができることは:

  1. 巨大なテーブルを保持するファイルを別のドライブ、たとえば、低速で大きなドライブにコピーします。
  2. 元の場所から他のドライブの新しい場所へのシンボリックリンクを作成します。
  3. vacuumdb --fullを実行すると、もう一方のディスクからデータが読み取られ、元のデータディスクに最終テーブルが書き込まれます。
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.