这是我提出的关于计算每列唯一的行列表统计信息的最佳方法的问题的延续,可以在此处找到(以及表模式)
我有一个表,其中包含数百万行股票数据,我想计算这些行上的自定义聚合。这个想法是将每个输入值附加到状态转换函数中。然后 Finalfunc 将计算该数组上的数字。聚合定义为:
create or replace aggregate RSI(input float8) (
SFUNC=tech_float8_accum,
STYPE=float8[],
FINALFUNC=RSI_Func
);
我在 plpython 中天真地实现了数组聚合函数:
-- Append the next input value to the state array
CREATE OR REPLACE function tech_float8_accum(agg float8[], input float8)
returns float8[]
AS $$
return agg + [input] if agg != None else [input]
$$ LANGUAGE plpython3u;
Finalfunc 也是用 plpython 编写的,根据经验,至少在数据库上下文之外,它速度相当快,因为它在底层使用了 Cython。
CREATE OR REPLACE FUNCTION RSI_Func(input float8[], out val float8)
AS $$
import talib
import numpy as np
cd=np.array(input)
rsi = talib.RSI(cd)
return rsi[-1]
$$ LANGUAGE plpython3u;
目前使用情况:
select "security", RSI(ordered.close)
from (
select "security", close
from stocks_data.bars
where "timeframe" = '1d'
and "timestamp" >= '2022-11-02'::timestamp
order by "timestamp" asc
) as ordered
group by ordered.security;
这大约需要3 分钟,而实际上我需要大约 3 秒或更短的时间,就像内置的 AVG 功能提供的那样。
我可以做些什么来彻底改进这种方法,还是应该完全采用另一种方法?内存中的数据太多了。
您应该检查您的 中花费了多少时间,但是您可以通过用 SQL 编写它来
FINALFUNC
加快速度:SFUNC
为了简单起见,我省略了对 NULL 数组的检查。为了弥补这一点,我们需要
INITCOND
在聚合定义中添加一个:如果这仍然不够快,您可以用 C 编写函数。
下次,请将执行计划添加为格式化文本,而不是图像。