避免在 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 函数来避免错误。这样一来,我每个公司只有一笔交易,而且我不会获得很多锁。
我有两个 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 函数来避免错误。这样一来,我每个公司只有一笔交易,而且我不会获得很多锁。