6

私のプロジェクトでは、2,300 万件のレコードと約 6 つのフィールドがあり、そのテーブルのインデックスが作成されています。

前に、Thinking Sphinx 検索用にデルタ列を追加することをテストしましたが、データベース全体のロックを 1 時間保持することになります。その後、ファイルが追加され、インデックスを再構築しようとすると、これはデータベース ロックを約 4 時間保持するクエリです。

"update user_messages set delta = false where delta = true"

サーバーを構成するために、db dump から新しいデータベースを作成し、それをデータベースとして昇格させて、サーバーを稼働できるようにしました。

今私が探しているのは、テーブルロックなしでテーブルにデルタ列を追加することは可能ですか? 列deltaが追加されると、インデックス再構築コマンドを実行すると上記のクエリが実行され、サーバーが長時間ブロックされるのはなぜですか?

PS .: 私は Heroku を使用しており、Postgres を ika db モデルで使用しています。

4

2 に答える 2

8

Postgres 11 以降

Postgres 11 以降、テーブルの書き換えが必要なのは揮発性のデフォルト値のみです。マニュアル:

volatile を持つ列を追加しDEFAULTたり、既存の列の型を変更したりするには、テーブル全体とそのインデックスを書き換える必要があります。

大胆強調鉱山。false不変です。で列を追加するだけDEFAULT falseです。超高速、仕事完了:

ALTER TABLE tbl ADD column delta boolean DEFAULT false;

Postgres 10 以前、または volatile の場合DEFAULT

またはなしで新しい列を追加すると、通常はテーブルの書き換えが強制されず、非常に安価です DEFAULTDEFAULT NULL実際の値を書き込むだけで、新しい行が作成されます。しかし、マニュアルを引用すると:

句を使用して列を追加しDEFAULTたり、既存の列のタイプを変更したりするには、テーブル全体とそのインデックスを書き換える必要があります。

UPDATEPostgreSQL では、行の新しいバージョンを書き込みます。あなたの質問はすべての情報を提供するわけではありませんが、それはおそらく何百万もの新しい行を書き込むことを意味します.

その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;
于 2012-05-02T11:26:19.447 に答える
0

1つの列で別のテーブルを追加できます。そのような長いロックはありません。もちろん、別の列、最初の列への外部キーが必要です。

インデックスには、「CREATE INDEX CONCURRENTLY」を使用できます。このテーブルでは、あまりにも重いロックを使用しませんhttp://www.postgresql.org/docs/9.1/static/sql-createindex.html

于 2012-05-02T11:47:28.503 に答える