PostgreSQL 9.0 Windows本番サーバーのスペースが不足しています。
100GBデータベースには、TOASTされたバイナリデータを含む大きなテーブルがあります。一部の行を削除したため、スペースをO/Sに戻す必要があります。
テーブルを完全に書き換えるのに十分なスペースがないため、CLUSTER
、VACUUM FULL
、およびpg_repack
をすべて読み取ると、テーブルを書き換える必要があります。私のgoogle-fuはこれまで何かを見つけるには不十分でした。
ある程度のダウンタイムは許容されます(約2時間)。ただし、バックアップ/復元が目的に対して遅すぎるため、ステップの間にデータベースを削除することにも熱心ではありません。
質問:テーブル全体を書き換えずにディスク領域をO/Sに戻すにはどうすればよいですか?
(これは本番サーバーなので、ソリューションは信頼できる/推奨/サポートされている必要があります)。
(追伸:何らかの方法でテーブルを再構築できる場合、使用可能な別のより大きなディスクを使用できます。テーブルスペース?)
CLUSTER
/VACUUM FULL
/ pg_repack
(すべてが自動的にロックを管理する)以外のものを使用する場合は、テーブルへの同時書き込みがないことを確認する必要があります。テーブルを排他的にロックし、すべてを1つのトランザクションで実行するか、同時変更を回避するためにすべての接続をシャットダウンします。
TABLESPACE
はい、あなたの最後のアイデアはうまくいくかもしれません。他のディスクに新しいテーブルスペースを作成します。
CREATE TABLESPACE ts1 LOCATION '/data/disk2';
次に、新しいテーブルスペースにテーブルの最適化されたコピーを作成します。
CREATE TABLE new_tbl
TABLESPACE ts1 AS
SELECT * FROM tbl
ORDER BY .... -- ORDER BY is optional
コピーはデッドローなしで密にパックされます。
次に、古いディスクを削除し、新しいディスクの名前を変更して、新しいディスクを使い続けることができます。
または、何らかの理由で古いディスクに保持する必要がある場合は、古いテーブルを削除し、新しいテーブルの名前を変更して、デフォルトに戻しますテーブルスペース。このステップはずっと速くなりました:
ALTER TABLE tbl SET TABLESPACE pg_default
このフォームは、テーブルのテーブルスペースを指定されたテーブルスペースに変更し、テーブルに関連付けられたデータファイルを新しいテーブルスペースに移動します。テーブルのインデックスがあっても移動されません。ただし、追加の
SET TABLESPACE
コマンドを使用して個別に移動できます。CREATE TABLESPACE
もご覧ください。
どちらの方法でも、すべての依存オブジェクトを(再)作成することを忘れないでください。インデックス、外部キー、ビュー、...
まあ、最初はALTER TABLE tbl SET TABLESPACE ...
を使用できますが、テーブルは要求どおりに最適化されず、そのまま移動されます。しかし、pg_repackなどを実行するのに十分な余裕があります。
COPY
完全なバックアップ/復元には時間がかかりすぎる可能性がありますが、問題のテーブルに対してのみ実行できます。
COPY tbl TO '/path/to/other/disk/tbl.pgsql';
TRUNCATE tbl;
COPY tbl FROM '/path/to/other/disk/tbl.pgsql';
これでテーブルがぎゅっと詰まっています。
If十分なRAMがある場合、RAMの一時テーブルを使用して同様のことを行うことができます。はるかに速くなります。詳細な手順:
ご使用の環境に、このテーブルの「実際のデータ(削減後)」のサイズよりも多くのディスク容量がある場合。 pg_reorgを使用して、このテーブルの膨張スペースを減らすことができます。または、londiste3インクリメントを使用してこのテーブルをコピーし、交換にかかる時間を短縮できます。ただし、envにこのテーブルよりも多くのスペースがない場合は、削減できません。
ヒープページ内のタプルを削除できる場合に、膨らみスペースを減らす別の方法があります。この方法では、追加スペースを減らして膨らみテーブルを減らします。 LIKE exp:
pg93@db-172-16-3-150-> psql
psql (9.3.3)
Type "help" for help.
digoal=# create table t_bloat(id int primary key, info text, crt_time timestamp);
CREATE TABLE
digoal=# insert into t_bloat select generate_series(1,100000),md5(random()::text),clock_timestamp();
INSERT 0 100000
digoal=# delete from t_bloat where id<>100000;
DELETE 99999
digoal=# vacuum t_bloat;
VACUUM
digoal=# vacuum t_bloat;
VACUUM
digoal=# select relpages from pg_class where relname='t_bloat';
relpages
----------
233
(1 row)
digoal=# insert into t_bloat select generate_series(1,100),md5(random()::text),clock_timestamp();
INSERT 0 100
digoal=# select split_part(ctid::text,',',1) from t_bloat group by 1;
split_part
------------
(0
(232
(2 rows)
digoal=# begin;
BEGIN
digoal=# create temp table t_bloat_tmp(like t_bloat);
CREATE TABLE
digoal=# insert into t_bloat_tmp select * from t_bloat where split_part(ctid::text,',',1)='(232';
INSERT 0 1
digoal=# delete from t_bloat where split_part(ctid::text,',',1)='(232';
DELETE 1
digoal=# insert into t_bloat select * from t_bloat_tmp ;
INSERT 0 1
digoal=# end;
COMMIT
digoal=# vacuum t_bloat;
VACUUM
digoal=# select split_part(ctid::text,',',1) from t_bloat group by 1;
split_part
------------
(0
(1
(2 rows)
digoal=# select relpages from pg_class where relname='t_bloat';
relpages
----------
2
(1 row)
あなたは注意ロックを握ります、これは単なる考えです。