Postgres 11 以降
Postgres 11 以降、テーブルの書き換えが必要なのは揮発性のデフォルト値のみです。マニュアル:
volatile を持つ列を追加しDEFAULT
たり、既存の列の型を変更したりするには、テーブル全体とそのインデックスを書き換える必要があります。
大胆強調鉱山。false
不変です。で列を追加するだけDEFAULT false
です。超高速、仕事完了:
ALTER TABLE tbl ADD column delta boolean DEFAULT false;
Postgres 10 以前、または volatile の場合DEFAULT
またはなしで新しい列を追加すると、通常はテーブルの書き換えが強制されず、非常に安価です DEFAULT
。DEFAULT NULL
実際の値を書き込むだけで、新しい行が作成されます。しかし、マニュアルを引用すると:
句を使用して列を追加しDEFAULT
たり、既存の列のタイプを変更したりするには、テーブル全体とそのインデックスを書き換える必要があります。
UPDATE
PostgreSQL では、行の新しいバージョンを書き込みます。あなたの質問はすべての情報を提供するわけではありませんが、それはおそらく何百万もの新しい行を書き込むことを意味します.
そのUPDATE
場で実行中に、テーブルの大部分が影響を受け、テーブルを排他的にロックできる場合は、一括UPDATE
を実行する前にすべてのインデックスを削除し、後で再作成します。こっちの方が早いです。マニュアルの関連アドバイス。
データ モデルと使用可能なディスク容量が許せばCREATE
、バックグラウンドで新しいテーブルを作成し、次に 1 つのトランザクションDROP
で古いテーブルとRENAME
新しいテーブルを作成します。関連している:
バックグラウンドで新しいテーブルを作成している間: すべての変更を一度に同じ行に適用します。更新が繰り返されると、新しい行バージョンが作成され、不要なタプルが残されます。
制約のために元のテーブルを削除できない場合TRUNCATE
、もう 1 つの手っ取り早い方法は、一時テーブル (元のテーブル) を作成しINSERT
、新しい行をまとめて並べ替えることです (それがパフォーマンスに役立つ場合)。1回の取引ですべて。このようなもの:
BEGIN
SET temp_buffers = 1000MB; -- or whatever you can spare temporarily
-- write-lock table here to prevent concurrent writes - if needed
LOCK TABLE tbl IN SHARE MODE;
CREATE TEMP TABLE tmp AS
SELECT *, false AS delta
FROM tbl; -- copy existing rows plus new value
-- ORDER BY ??? -- opportune moment to cluster rows
-- DROP all indexes here
TRUNCATE tbl; -- empty table - truncate is super fast
ALTER TABLE tbl ADD column delta boolean DEFAULT FALSE; -- NOT NULL?
INSERT INTO tbl
TABLE tmp; -- insert back surviving rows.
-- recreate all indexes here
COMMIT;