PostgresQL に非常に大きなデータベース テーブルがあり、「コピー済み」のような列があります。すべての新しい行はコピーされずに開始され、後でバックグラウンド プログラムによって別のものに複製されます。そのテーブルには部分インデックス「btree(ID) WHERE replicated=0」があります。バックグラウンド プログラムは、最大 2000 エントリ (LIMIT 2000) の選択を行い、それらを処理してから、2000 の準備された SQL コマンドを使用して 1 つのトランザクションで変更をコミットします。
ここでの問題は、この複製された値をリセットするオプションをユーザーに提供し、すべてをゼロに戻すことです。
更新テーブル セット レプリケート = 0;
不可能です:
- とても時間がかかります
- MVCCのため、テーブルのサイズが重複しています
- 1 つのトランザクションで実行されます。失敗するか、通過します。
この場合、実際にはトランザクション機能は必要ありません。システムがダウンした場合、システムはその一部のみを処理します。
その他のいくつかの問題:
update set replicated=0 where id >10000 and id<20000
また、悪いことです。テーブル全体でシーケンシャル スキャンを実行するため、遅すぎます。そうしないと、シークが多すぎるため、まだ遅くなります。
私が本当に必要としているのは、すべての行を通過し、それらを変更し、巨大なトランザクションに縛られない方法です。
奇妙なことに、
UPDATE table
SET replicated=0
WHERE ID in (SELECT id from table WHERE replicated= LIMIT 10000)
良いことではありますが、これも遅いです: DISK 順にテーブルを調べます...
(その場合、これをカバーする索引もあったことに注意してください)
(Mysql のような更新 LIMIT は PostgresQL では使用できません)
ところで: 本当の問題はもっと複雑で、既に展開されている組み込みシステムについて話しているので、リモートでスキーマを変更することは困難ですが、残念ながら PostgresQL 7.4 である可能性があります。
私が話している行の量は、たとえば 90000000 です。データベースのサイズは、数十ギガバイトになる場合があります。
データベース自体には 5 つのテーブルしか含まれておらず、そのうちの 1 つは非常に大きなものです。しかし、これは悪い設計ではありません。これらの組み込みボックスは、ERP システムなどではなく、1 種類のエンティティでのみ動作するからです。
何か案は?