UPDATE Query需要很长的PostgreSQL

时间:2017-01-18 09:44:35

标签: sql database postgresql

我想UPDATEmyTable(335379行)中的几行。

CREATE OR REPLACE FUNCTION costs_f(
someFloat float) RETURNS void AS
$$
BEGIN
UPDATE ways 
SET cost_time = CASE WHEN $1 = -1.0 THEN -1 ELSE anotherFloat * $1 END
FROM (SELECT w.gid AS id,
mc.name,
w.someCosts
FROM myTable mt
JOIN myClasses mc
ON mt.class_id = mc.class_id) AS tempTable
WHERE gid = id AND tempTable.name_name = $2;
END
$$
language 'plpgsql';

然后在另一个函数

中调用此函数
CREATE OR REPLACE FUNCTION update_costs_f(
someFloat float) RETURNS void AS
$$
DECLARE
someArr varchar[] := ARRAY['a', 'b', 'c', 'd',
    'e', 'f', 'g', 'h', 'i', 
    'j', 'k', 'l',
    'm', 'n', 'o', 'p', 
    'q', 'r', 's', 't', 'ul', 'v'];
i text;
BEGIN
FOREACH i IN ARRAY someArr LOOP
    PERFORM costs_f($1, i);
END LOOP;
END
$$
language 'plpgsql';

然后我做

SELECT update_costs_f(10.0);

然而,这需要很长时间! 有没有办法提高速度?

*注意:此代码是抽象的。在第二个函数中有更多ForEach循环。我有几个阵列。

1 个答案:

答案 0 :(得分:1)

1。摆脱tempTable.name_name = $ 2;

正如@a_horse_with_no_name所说,您不应该运行多个更新语句。

我发现您PERFORM costs_f($1, i)中的每封信都多次致电someArr。而不是多次调用它,只需调用一次并使用in运算符,例如:

AND tempTable.name_name in($2);

2。将更新拆分为2个语句

您应该将更新语句拆分为两个语句:

UPDATE ways 
SET cost_time = -1.0 FROM tempTable 
WHERE gid = id AND tempTable.name_name = $2 AND
$1 = -1.0 ;

UPDATE ways 
SET cost_time =anotherFloat * $1 FROM tempTable 
WHERE gid = id AND tempTable.name_name = $2 AND
NOT ($1 = -1.0) ;

注意:仅使用tempTable而不是完整的嵌套子句/别名

进行简化

3。将条件移动到嵌套的Aliased From SubQuery

马上就可以看到你可以将条件name_name = $2直接移到from aliased subquery

FROM (SELECT w.gid AS id,
mc.name,
w.someCosts
FROM myTable mt
JOIN myClasses mc
ON mt.class_id = mc.class_id 
WHERE name_name = $2 ) AS tempTable
WHERE gid = id;

All Together

CREATE OR REPLACE FUNCTION update_costs_f(
someFloat float) RETURNS void AS
$$
DECLARE
someArr varchar[] := ARRAY['a', 'b', 'c', 'd',
    'e', 'f', 'g', 'h', 'i', 
    'j', 'k', 'l',
    'm', 'n', 'o', 'p', 
    'q', 'r', 's', 't', 'ul', 'v'];
i text;
BEGIN
PERFORM costs_f($1, someArr );
END
$$
language 'plpgsql';


CREATE OR REPLACE FUNCTION costs_f(
someFloat float) RETURNS void AS
$$
BEGIN
UPDATE ways 
SET cost_time = -1.0
FROM (SELECT w.gid AS id,
mc.name,
w.someCosts
FROM myTable mt
JOIN myClasses mc
ON mt.class_id = mc.class_id
WHERE $1 = -1.0 AND gid = id AND tempTable.name_name = ANY($2);
) AS tempTable;    

UPDATE ways 
SET cost_time =anotherFloat * $1 
FROM (SELECT w.gid AS id,
mc.name,
w.someCosts
FROM myTable mt
JOIN myClasses mc
ON mt.class_id = mc.class_id
WHERE NOT($1 = -1.0) AND gid = id AND tempTable.name_name =ANY($2);
) AS tempTable;

END
$$
language 'plpgsql';

最后

您可以使用IF语句,以便不运行两个SQL更新语句...

请参阅:PostgreSQL IF statement 例如:

IF ($1 = -1.0) THEN
   ...
ELSE 
  ...
END IF;