Esta é uma continuação de uma pergunta que fiz sobre a melhor maneira de calcular estatísticas em uma lista de linhas exclusivas por coluna, que pode ser encontrada aqui (junto com o esquema da tabela)
Eu tenho uma tabela que contém milhões de linhas de dados de estoque e quero calcular agregados personalizados nessas linhas. A ideia é anexar cada valor de entrada na função de transição de estado. Então o finalfunc calculará o número neste array. O agregado é definido como:
create or replace aggregate RSI(input float8) (
SFUNC=tech_float8_accum,
STYPE=float8[],
FINALFUNC=RSI_Func
);
Onde implementei ingenuamente a função de agregação de array no 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;
O finalfunc também é escrito em plpython e, por experiência própria, é bastante rápido, pelo menos fora do contexto de banco de dados, já que usa Cython nos bastidores.
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;
Uso atual:
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;
Isso leva aproximadamente 3 minutos , quando na realidade preciso de algo em torno de 3 segundos ou menos, como a função AVG integrada oferece.
Há algo que eu possa fazer para melhorar drasticamente essa abordagem ou devo adotar outra abordagem? São muitos dados para trazer na memória.
Você deve verificar quanto tempo é gasto no seu
FINALFUNC
, mas pode agilizarSFUNC
escrevendo-o em SQL:Para simplificar, omiti a verificação de um array NULL. Para compensar isso, precisamos adicionar um
INITCOND
à definição agregada:Se isso ainda não for rápido o suficiente, você poderá escrever as funções em C.
Da próxima vez, adicione planos de execução como texto formatado, não como imagem.