[pgsql-jp: 38101] Re: コミット待ちトランザクションのメモリ消費量について
Yoshiyuki Asaba
y-asaba @ sraoss.co.jp
2007年 2月 27日 (火) 22:33:09 JST
浅羽です。
From: "EBIHARA, Yuichiro" <ebihara @ iplocks.co.jp>
Subject: [pgsql-jp: 38093] Re: コミット待ちトランザクションのメモリ消費量について
Date: Tue, 27 Feb 2007 19:02:48 +0900
> 実際、数千万件を一括更新するUPDATE文を実行したときに、以下のようなエ
> ラーが発生してバックエンドが異常終了する例は7.1で見たことがあります。
>
> ERROR: Memory exhausted in AllocSetAlloc(108)
>
> バックエンドのプロセスサイズは概ね2GBでした。
AFTER トリガー(外部キー制約がある場合も含む)などがあるテーブルを 1 つ
の SQL で更新したりすると結構メモリを食います。
test=# create table mem1 (a int primary key);
test=# create table mem2 (a int references mem1);
test=# insert into mem1 select generate_series(1, 2000001);
test=# insert into mem2 select generate_series(1, 2000000);
test=# update mem2 set a = a + 1;
1 行ごとにトリガイベントをキューに追加していきます。全部更新し終わった
あとにキューを取り出して、いろいろと処理します。ざっと見ただけなので間
違っているかもしれませんが、キューの追加で、8.2 の場合は少なくとも 32
バイトは使います。200 万件あると 200万 * 32 バイト必要になります。
postgresql-8.2.3/src/backend/commands/trigger.c:AfterTriggerSaveEvent()
3360行目付近
/*
* Create a new event.
*/
new_event = (AfterTriggerEvent)
ココ--> MemoryContextAlloc(*cxtptr, sizeof(AfterTriggerEventData));
new_event->ate_next = NULL;
反対に、トリガの無いテーブルを UPDATE してもあまりメモリを食わないのが
わかります。
test=# create table mem3 as select generate_series(1, 2000000) as a;
test=# update mem3 set a = a+1;
--
Yoshiyuki Asaba
y-asaba @ sraoss.co.jp
pgsql-jp メーリングリストの案内