UPDATE 查询需要很长时间 PostgreSQL
Posted
技术标签:
【中文标题】UPDATE 查询需要很长时间 PostgreSQL【英文标题】:UPDATE Query takes very long PostgreSQL 【发布时间】:2017-01-18 09:44:35 【问题描述】:我想UPDATE
myTable
表中的几行(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
循环。我有几个数组。
【问题讨论】:
您对代码进行了模糊处理,以至于它不再有效。您正在循环内将字符串传递给costs_f()
,但该函数需要一个浮点值。该函数还使用未在任何地方声明的变量anotherfloat
。而且,不相关但是:比较浮点数是否相等可能会产生许多令人惊讶的结果:floating-point-gui.de
它仍然无效 - 但给出的示例可以简化为单个更新语句并且不需要函数。所以你的抽象没有帮助。
@a_horse_with_no_name 当然我可以把它写成一个语句。但是这些函数在程序不同部分的不同位置被调用。所以我需要它们具有两种不同的功能。我感兴趣的是,当我以执行函数的方式执行更新时,为什么更新需要这么长时间。
因为您正在进行缓慢的逐行更新。更新多行的单个语句总是比更新单行的多个语句更快。改善这一点的唯一方法是摆脱缓慢、低效和不可扩展的逐行处理
@a_horse_with_no_name 啊,谢谢。你能告诉我要找什么吗?
【参考方案1】:
1。摆脱 tempTable.name_name = $2;
正如@a_horse_with_no_name 所说,您不应该运行多个更新语句。
我看到您为someArr
中的每个字母多次调用PERFORM costs_f($1, i)
。不要多次调用它,而是调用一次并使用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 而不是完整嵌套的 subuery/alias 来简化
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;
齐心协力
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;
【讨论】:
谢谢。您在costs_f
中缺少函数参数。调用它时,(PERFORM costs_f($1, someArr );
你的传递 $1
和 someArr
但你没有在这里定义它CREATE OR REPLACE FUNCTION costs_f( someFloat float) RETURNS void AS
。
@Stophface Yeh...但是您是否尝试过更改以检查速度?
我正在尝试实施。它嘲笑阵列。我更改了CREATE OR REPLACE FUNCTION costs_f( someFloat float someText text[]) RETURNS void AS
和SELECT PERFORM costs_f($1, someArr::text[]);
但它说ERROR: operator does not exist: text = text[] LINE 10: WHERE $1 = -1.0 AND gid = id AND tempTable.name_name in ($2) HINT: No operator matches the given name and argument type(s). You might need to add explicit type casts.
而错误消息中花哨的^
指向IN
@Stophface dbrnd.com/2015/09/string-array-input-parameter-in-postgresql ? ArrayText character varying[]
。也尝试用 ANY 函数代替 IN。 ***.com/q/30298031/1688441 ... ANY(ArrayText)
我第一次尝试过。我更改为CREATE OR REPLACE FUNCTION costs_f( someFloat float someText character varying[])
和类型转换以及:: character varying[]
。同样的错误。与varchar[]
的结果相同。我已经尝试将IN
更改为ANY
。 ERROR: syntax error at or near "ANY" text = text[] LINE 10: WHERE $1 = -1.0 ANY gid = id AND
以上是关于UPDATE 查询需要很长时间 PostgreSQL的主要内容,如果未能解决你的问题,请参考以下文章
cocoapods:pod update 和 pod install 需要很长时间