2

何百万ものレコードがあるテーブルがあります。そのテーブルのみの合計サイズは、6 ~ 7 ギガバイトです。このテーブルは、私のアプリケーション ログ テーブルです。このテーブルは非常に急速に成長しています。これは理にかなっています。ここで、レコードをログ テーブルからバックアップ テーブルに移動したいと考えています。ここにシナリオがあり、ここに私の質問があります。

Table Log_A
Insert into Log_b select * from Log_A;
Delete from Log_A;

postgres データベースを使用しています。質問は

このクエリを実行すると、Log_A のすべてのレコードが物理メモリにロードされますか? 注: 上記のクエリは両方とも、ストアド プロシージャ内で実行されます。いいえの場合、どのように機能しますか?

この質問がすべてのデータベースに当てはまることを願っています。

誰かがこれについて私にアイデアを提供してくれることを願っています。

4

3 に答える 3

1

PostgreSQLでは、シーケンシャルスキャンを実行し、いくつかのレコードをにロードしshared_buffers、それらを挿入し、ダーティバッファを書き出し、続行する可能性があります。

すべてのレコードはメインメモリを通過しますが、すべてを一度にメモリに保存する必要はありません。それらはすべて通常のバッファ読み取り(pread)を使用してディスクから読み取られるため、オペレーティングシステムのディスクキャッシュ影響を与え、他のデータをキャッシュからプッシュする可能性があります。

他のデータベースは異なる場合があります。SELECT処理する前に全体を実行できるINSERTものもあります(ただし、深刻なものが実行された場合は驚きます)。OSキャッシュの影響を回避するために、読み取りまたはrawディスクI / Oを使用するものもあるO_DIRECTため、バッファキャッシュの影響は異なる場合があります。SELECTただし、データベース全体をメモリにロードすることに依存しているデータベースがあるとしたら、私は驚かれることでしょう。

PostgreSQLが何をどのように行っているかを知りたい場合は、EXPLAINandEXPLAIN (BUFFERS, ANALYZE)コマンドが非常に便利です。マニュアルを参照してください。

この目的のために、書き込み可能な共通テーブル式が興味深いと思うかもしれません。これにより、これらすべてを1つのステートメントで実行できます。この単純なケースでは、おそらくほとんどメリットはありませんが、より複雑なデータ移行では大きなメリットになる可能性があります。

BEGINところで、とでラップされたクエリのペアを実行するようにしてCOMMITください。

于 2012-10-17T22:27:34.350 に答える
0

おそらくそうではありません。

各レコードは個別に処理されます。この特定のクエリは、正常に実行するために他のレコードの知識を持っている必要はありません。そのため、特定の瞬間にメモリに存在する必要がある唯一のレコードは、現在処理中のレコードです。

ただし、データベースがテーブル全体をロードすることでより高速に実行できると考えるかどうかに大きく依存します。クエリの実行プランを確認してください。

于 2012-10-17T17:18:35.150 に答える
0

セットアップで許可されている場合は、古いテーブルの名前を変更して、新しい空のテーブルを作成してください。コピーがまったく行われないため、明らかにはるかに高速です。

ALTER TABLE log_a RENAME TO log_b;
CREATE TABLE log_a (LIKE log_b INCLUDING ALL);

このLIKE句は、(名前が変更された) 古いテーブルの構造をコピーします。INCLUDING ALLデフォルト、制約、インデックスなどが含まれます...

テーブルまたはその他のあまり一般的でない依存関係に依存する外部キー制約またはビュー (ただし、plpgsql 関数のクエリではない) は、このルートのハードルになる可能性があります。それらが新しいテーブルを指すようにするには、それらを再作成する必要があります。しかし、あなたが説明したようなログテーブルには、おそらくそのような依存関係はありません。

これにより、テーブルの排他ロックが取得されます。典型的な書き込みアクセスはINSERTあなたの場合だけになると思いますか? 同時アクセスに対処する 1 つの方法は、別のスキーマsearch_pathに新しいテーブルを作成し、アプリケーション ユーザーの を変更することです。その後、アプリケーションは、並行性の問題なしに新しいテーブルへの書き込みを開始します。もちろん、INSERTこれを有効にするために、ステートメントでテーブル名をスキーマ修飾することはありません。

CREATE SCHEMA log20121018;
CREATE TABLE log20121018.log_a (LIKE log20121011.log_a INCLUDING ALL);
ALTER ROLE myrole SET search_path = app, log20121018, public;

または、search_path有効なレベルで設定を変更します: グローバル、データベースごと、ロールごと、セッションごと、関数ごと...

于 2012-10-18T03:24:05.837 に答える