[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 メーリングリストの案内