3

特定の数のテスト レコードを挿入するクエリがあります。次のようになります。

CREATE OR REPLACE FUNCTION _miscRandomizer(vNumberOfRecords int)
RETURNS void AS $$
declare
    -- declare all the variables that will be used
begin
    select into vTotalRecords count(*) from tbluser;
    vIndexMain := vTotalRecords;

    loop
        exit when vIndexMain >= vNumberOfRecords + vTotalRecords;

        -- set some other variables that will be used for the insert
        -- insert record with these variables in tblUser
        -- insert records in some other tables
        -- run another function that calculates and saves some stats regarding inserted records

        vIndexMain := vIndexMain + 1;
        end loop;
    return;
end
$$ LANGUAGE plpgsql;

300 レコードに対してこのクエリを実行すると、次のエラーがスローされます。

********** Error **********

ERROR: out of shared memory
SQL state: 53200
Hint: You might need to increase max_locks_per_transaction.
Context: SQL statement "create temp table _counts(...)"
PL/pgSQL function prcStatsUpdate(integer) line 25 at SQL statement
SQL statement "SELECT prcStatsUpdate(vUserId)"
PL/pgSQL function _miscrandomizer(integer) line 164 at PERFORM

関数 prcStatsUpdate は次のようになります。

CREATE OR REPLACE FUNCTION prcStatsUpdate(vUserId int)
RETURNS void AS
$$
declare
    vRequireCount boolean;
    vRecordsExist boolean;
begin
    -- determine if this stats calculation needs to be performed
    select into vRequireCount
        case when count(*) > 0 then true else false end
    from tblSomeTable q
    where [x = y]
      and [x = y];

    -- if above is true, determine if stats were previously calculated
    select into vRecordsExist
        case when count(*) > 0 then true else false end
    from tblSomeOtherTable c
    inner join tblSomeTable q
       on q.Id = c.Id
    where [x = y]
      and [x = y]
      and [x = y]
      and vRequireCount = true;

    -- calculate counts and store them in temp table
    create temp table _counts(...);
    insert into _counts(x, y, z)
    select uqa.x, uqa.y, count(*) as aCount
    from tblSomeOtherTable uqa
    inner join tblSomeTable q
       on uqa.Id = q.Id
    where uqa.Id = vUserId
      and qId = [SomeOtherVariable]
      and [x = y]
      and vRequireCount = true
    group by uqa.x, uqa.y;

    -- if stats records exist, update them; else - insert new
    update tblSomeOtherTable 
    set aCount = c.aCount
    from _counts c
    where c.Id = tblSomeOtherTable.Id
      and c.OtherId = tblSomeOtherTable.OtherId
      and vRecordsExist = true
      and vRequireCount = true;

    insert into tblSomeOtherTable(x, y, z)
    select x, y, z
    from _counts
    where vRecordsExist = false
      and vRequireCount = true;

    drop table _counts;
end;
$$ LANGUAGE plpgsql;

エラーはメモリがどこかに蓄積された結果であるように見えますが、一時テーブルを作成し、それを使用してすぐにドロップするため (したがって、メモリを解放することを理解しています)、それがどのように可能になるかわかりません。

アップデート

私が持っている実際の関数を表すために prcStatsUpdate 関数を更新しました。テーブル名と列名を一般的な名前に置き換えただけです。今回初めて投稿しなかった理由は、ほとんどが非常に単純な sql 操作であり、問​​題はないと思っていたからです。

また、どこから行数を数え始めますか? エラーは 25 行目にありますが、25 行目はwhere句の条件であるため、最初からカウントを開始すると、エラーになることはありません。から数えbeginますか?

何か案は?

4

2 に答える 2

10

一時テーブルが削除されると、トランザクションが終了するまでロックは解放されません。

関連する回答を参照してください。

可能であれば、コードを再編成して、関数の外側で一時テーブルを作成し、関数の内側でそれを切り捨て/移入する必要があります。

于 2013-05-13T17:32:16.853 に答える