我在这些函数中使用了一个非常大的csv文件(大约716k行)。他们使用一个小文件快速工作,但是如此大量的行我已经离开了一个小时,它甚至没有结束。 事情是在某种程度上我称之为'LIMPIA_REPETIDOS()'函数
CREATE OR REPLACE FUNCTION LIMPIA_REPETIDOS()
RETURNS VOID AS $$
DECLARE
REP RECORD;
cursor1 CURSOR FOR SELECT DISTINCT usuario, fecha_hora_ret FROM auxi;
begin
open cursor1;
LOOP
FETCH cursor1 INTO REP;
EXIT WHEN NOT FOUND;
PERFORM GUARDA(REP.usuario, REP.fecha_hora_ret);
END LOOP;
CLOSE cursor1;
end;
$$ LANGUAGE PLPGSQL;
CREATE OR REPLACE FUNCTION GUARDA
(myid auxi.usuario%TYPE, my_time auxi.fecha_hora_ret%type) RETURNS VOID AS $$
DECLARE
mycursor CURSOR FOR
SELECT * FROM auxi
WHERE myid = usuario AND my_time = fecha_hora_ret
ORDER BY tiempo_uso ASC;
CANT INT;
devolucion TIMESTAMP;
mystruct RECORD;
mystruct2 RECORD;
BEGIN
OPEN mycursor;
CANT = 0;
FETCH mycursor INTO mystruct;
FETCH mycursor INTO mystruct2;
IF mystruct2.usuario = mystruct.usuario AND mystruct2.fecha_hora_ret = mystruct.fecha_hora_ret THEN
devolucion = crear_fecha_hora_devolucion(mystruct2.tiempo_uso, mystruct2.fecha_hora_ret);
INSERT INTO RECORRIDO_FINAL VALUES(mystruct2.periodo, mystruct2.usuario, mystruct2.fecha_hora_ret, mystruct2.est_origen, mystruct2.est_origen, devolucion);
ELSE
devolucion = crear_fecha_hora_devolucion(mystruct.tiempo_uso, mystruct.fecha_hora_ret);
INSERT INTO RECORRIDO_FINAL VALUES(mystruct.periodo, mystruct.usuario, mystruct.fecha_hora_ret, mystruct.est_origen, mystruct.est_origen, devolucion);
END IF;
CLOSE mycursor;
END;
$$ LANGUAGE PLPGSQL;
我在这里做的是从一个名为'auxi'的表中选择行,该表包含该文件中的所有行(除了一些具有空值但速度足够快的行),然后将它们转移到另一个行。问题是当'auxi'中有两行或更多行具有'usuario'和'fecha_hora_ret'的相同值时,我必须通过'tiempo_uso'对它们进行排序,然后选择第二行。我不知道为什么需要这么多时间。 我怎样才能让它更快?
表auxi有PRIMARY KEY(periodo,usuario,fecha_hora_ret,est_origen,est_destino,tiempo_uso) 和table recorrido_final PRIMARY KEY(usuario,fecha_hora_ret)
我很绝望,我不知道该怎么办。
答案 0 :(得分:0)
代码中的LOOP和附加函数调用可能导致性能下降。您是否可以通过以下查询为其他PK列的每个组合选择tiempo_uso
的最大值:
select
periodo,
usuario,
fecha_hora_ret,
est_origen,
est_destino,
max(tiempo_uso) as max_tiempo_uso
from
auxi
group by
periodo,
usuario,
fecha_hora_ret,
est_origen,
est_destino;
并将其用作INSERT INTO语句的数据源?这避免了代码中的函数调用和循环。
答案 1 :(得分:0)
使用游标处理数据通常非常低效且不需要,因为在大多数情况下它会被set-prcessing取代。
如果您需要查找最新的行,您可以使用简单的ROW_NUMBER:
select periodo, usuario, fecha_hora_ret, est_origen, est_origen
,crear_fecha_hora_devolucion(tiempo_uso, fecha_hora_ret) as devolucion
FROM
(
select periodo, usuario, fecha_hora_ret, est_origen, est_origen
,crear_fecha_hora_devolucion(tiempo_uso, fecha_hora_ret) as devolucion
,row_number() -- most recent row per usuario/fecha_hora_ret
over (partition by usuario, fecha_hora_ret
ORDER BY tiempo_uso DESC) as rn
from auxi
) as dt
where rn = 1