値をNOT NULL
持つ列を追加するDEFAULT
場合-PostgreSQLはこの操作を最適化しますか?
テーブルにn行がある場合、最適化されていないalter-table-add-columnは、デフォルト値のn回の書き込みを生成します。最適化により、DBは即座に新しい列を作成し、適切なインデックスデータ構造でその列の非デフォルト値が見つからない場合に返されるデフォルト値のコピーを1つだけ保存します。
たとえば、Oracle 11gにはそのような最適化があります。
値をNOT NULL
持つ列を追加するDEFAULT
場合-PostgreSQLはこの操作を最適化しますか?
テーブルにn行がある場合、最適化されていないalter-table-add-columnは、デフォルト値のn回の書き込みを生成します。最適化により、DBは即座に新しい列を作成し、適切なインデックスデータ構造でその列の非デフォルト値が見つからない場合に返されるデフォルト値のコピーを1つだけ保存します。
たとえば、Oracle 11gにはそのような最適化があります。
回答:
PostgreSQLにはそのようなメカニズムはありません。
ただし、このようなテーブル変更による過度の影響を回避することはできます。
次のステートメントは、ステートメント/トランザクションの間、テーブルのアクセス排他ロックを取得します。
ALTER TABLE your_table
ADD COLUMN new_column integer NOT NULL DEFAULT 0;
このステートメントはカタログを変更し、新しい列がすべての行のデフォルト値を含むようにテーブル全体を書き換えます。テーブルに多くの行があり、十分な頻度でアクセスされている場合、一時的な問題が発生する可能性があります。
これを回避するには、排他ロックをできるだけ短くしてください。
ALTER TABLE your_table
ADD COLUMN new_column integer;
ALTER TABLE your_table
ALTER COLUMN new_column SET DEFAULT 0;
これは基本的にカタログへの(実際には2つの)変更(データ変更は発生しない)のみであるため、かなり高速に完了します。次に、ニーズとテーブルの使用法に応じて、新しい列を1ステップまたはバッチでデフォルトに更新し、完了したら、列をに設定できますNOT NULL
。
願いが叶うことについての更新: PostgreSQL 11にはこの機能があります。詳細については、https://www.depesz.com/2018/04/04/waiting-for-postgresql-11-fast-alter-table-add-column-with-a-non-null-default/を参照してください。
この機能は新しく、バージョン11に導入されました。
ALTER TABLE your_table
ADD COLUMN new_column integer NOT NULL DEFAULT 0;
上記は、この最適化の影響を受けるコマンドの1つです。ただし、必須でNOT NULL
はないことに注意してください。null以外のデフォルトで追加された新しい列はすべて最適化されます。このcommitfestでエントリを見つけることができます。「Postgres 11のミッシングリンク:デフォルトでの高速な列作成」というこの記事に関するすばらしい記事も確認する必要があります。
テーブルの排他的なテーブルロックを回避しようとしている場合は、Craig Ringerのアドバイスに従ってください。
DEFAULT
ALTER
DEFAULT
後で追加するため、新しく挿入された行に適用されますUPDATE
SNOT NULL
制約を追加します