とメモリ不足:何かがfoo
に挿入されたときにPostgresは、私は2つのテーブルを持っているトリガー
CREATE FUNCTION foo_before_insert()
RETURNS trigger AS
$BODY$
BEGIN
INSERT INTO bar (id, xyz)
VALUES (
NEW.id,
FooFunction(NEW.abc)
);
RETURN NEW;
END;
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
CREATE TRIGGER foo_before_insert
BEFORE INSERT ON foo
EXECUTE PROCEDURE foo_before_insert();
だから、何かがまたに挿入されています
CREATE TABLE foo (
id serial primary key,
abc text
);
CREATE TABLE bar (
id serial primary key,
xyz text
);
私はテーブルfoo
にトリガーを持っていますbar
であり、abc
カラムはFooFunction
によって操作されている。これは単純化されたバージョンです。
実世界FooFunction
は、経度と緯度のための2つの数値の引数を取り、単一のジオメトリ列を選択SELECT
クエリにfor loop
を行い、ジオメトリ列と入力して、いくつかのPostGISの機能を行い、およびブール値を返します。基本的に、この関数は、ポイントがポリゴンのセットから少なくとも1つのポリゴンの内部にあるかどうかを判断しようとしています。
は、ここでの機能の肉とジャガイモです:
FOR currentLinestring IN
SELECT linestring
FROM bla
WHERE yadda yadda...
LOOP
currentLinestring = ST_MakeLine(currentLinestring);
-- Can't make polygon with under 4 points
IF ST_NPoints(currentLinestring) < 4 THEN
EXIT;
END IF;
IF ST_Contains(ST_MakePolygon(currentLinestring), ST_SetSRID(ST_MakePoint(_lon, _lat), 4326)) = TRUE THEN
-- Is not out of bounds
RETURN FALSE;
END IF;
END LOOP;
-- Is out of bounds
RETURN TRUE;
キャッチ関数は(質量更新などの)とき、トリガ外に100%正常に動作しますが、あるとき、トリガ関数内Postgresの登りのメモリ使用量メモリがすべて使い果たされ、Postgresがクラッシュするまで登ります。これは、私がCOPY
で大規模なCSVを多分100kの行にしているときに起きています。
何が起こっているのですか?これをどうすれば解決できますか?
個人的には、スタックの深さ制限を使い切る前に、メモリ制限にぶつかる再帰トリガだと思われます。 –
@CraigRinger私はこれを可能性と考えていたが、そうは思わない。トリガー関数では、FooFunctionへの呼び出しを取り除き、挿入がうまくいった。 FooFunctionはSELECTを実行しているだけなので、どのように再帰的なトリガーを引き起こすかはわかりません。 – Tyler
PostGISは時折メモリ豚として知られています。 –