避免在 PostgreSQL 函数中使用 'out of shared memory error'

Avoid 'out of shared memory error' in PostgreSQL function

我有两个 table,一个叫做 companies_display 的 table 包含有关上市公司的信息,例如股票代码、市值等等,以及每个公司的历史股价的分区 table stock_prices。 我想计算每只股票的 beta 并将其写入 companies_display。 为此,我编写了函数 calculate_beta(ticker) 来计算它:

CREATE OR REPLACE FUNCTION calculate_beta (VARCHAR)
RETURNS float8 AS $beta$
DECLARE
    beta float8;
BEGIN
    WITH weekly_returns AS (
        WITH RECURSIVE
        spy AS (
            SELECT time, close FROM stock_prices WHERE ticker = 'SPY'
        ),
        stock AS (
            SELECT time, close FROM stock_prices WHERE ticker = 
        )
        SELECT
            spy.time,
            stock.close / LAG(stock.close) OVER (ORDER BY spy.time DESC) AS stock,
            spy.close / LAG(spy.close) OVER (ORDER BY spy.time DESC) AS spy
        FROM stock
        JOIN spy
        ON stock.time = spy.time
        WHERE EXTRACT(DOW FROM spy.time) = 1
        ORDER BY spy.time DESC
        LIMIT 52
    )
    SELECT 
        COVAR_SAMP(stock, spy) / VAR_SAMP(spy) INTO beta
    FROM weekly_returns
    ;
    RETURN beta;
END;
$beta$ LANGUAGE plpgsql;

该功能仅适用于少数几家公司,但当我尝试更新整个公司时 table

UPDATE companies_display SET beta = calculate_beta(ticker);

我收到共享内存不足错误,它说 max_locks_per_transaction 太低。 我的猜测是该函数为每个公司在 stock_prices table 上创建了一个锁,并且在 运行 完成之前不会删除它们. 我尝试的是创建一个循环

DO
$do$
DECLARE
    ticker_ VARCHAR;
BEGIN
    FOR ticker_ IN SELECT ticker FROM companies_display
    LOOP
        UPDATE companies_display
        SET beta = calculate_beta(ticker_)
        WHERE ticker = ticker_
        ;
    END LOOP;
END
$do$;

但是我运行遇到了同样的问题。 有没有办法在每次 beta 计算后解除对 stock_prices 的锁定或分批更新? 我的方法一次对大约 5 家公司有效。

如果有人遇到同样的问题,我通过从用于更新数据库的服务器调用 sql 函数来避免错误。这样一来,我每个公司只有一笔交易,而且我不会获得很多锁。