这是我从文件或文件夹路径中获取父母的功能:
CREATE OR REPLACE FUNCTION storage.__object_get_parents(p_object_path varchar, p_tolowercase boolean)
RETURNS varchar[] AS
$BODY$
DECLARE
_arr varchar[];
_parents varchar[];
_parent varchar;
_parent_prev varchar;
_object_path varchar;
_cnt int := 0;
_val varchar;
BEGIN
if p_tolowercase then
_object_path := lower(substr(p_object_path, 1, length(p_object_path)-1));
else
_object_path := substr(p_object_path, 1, length(p_object_path)-1);
end if;
_arr := string_to_array(_object_path, '/', '');
_parent_prev := '';
for i in 1 .. array_upper(_arr, 1)-1 loop
_val := _arr[i];
if _val IS NOT NULL then
_parent := _parent_prev || _val || '/';
_parents := array_append(_parents, _parent);
_cnt := _cnt + 1;
else
-- ignore double slashes: replace previsouly added element
_parent := _parent_prev || '/';
_parents[_cnt] := _parent;
end if;
_parent_prev := _parent;
end loop;
RETURN coalesce(_parents,'{}'::varchar[]);
EXCEPTION
WHEN OTHERS THEN
RAISE EXCEPTION 'function __object_get_parents() is failed! ErrCode (%) (%)', SQLSTATE, SQLERRM;
END;
$BODY$
LANGUAGE 'plpgsql' IMMUTABLE;
当我在一个包含许多组件的路径上运行它时,它真的很慢:
select array_length(storage.__object_get_parents('d2140247-ef9d-4d51-ac28-ba008c378720/H%3A/files/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/',false),1);
array_length
--------------
2145
(1 row)
Time: 13885.555 ms
如何提高速度?
答案 0 :(得分:1)
问题是您正在生成大量数据。如果你有一个长度约为8kB的字符串中的2145个父项,那么你会产生一个2145个元素的数组,这些元素的长度从一个小的开始到接近8kB,平均为4kB。因此,在2145年,父母会产生大约8MB的数据。你真的需要所有这些吗?你真的需要一个函数调用中的所有父母吗?
也许你应该告诉我们你真正想要的东西然后我们可以看到合适的功能是什么。
也就是说,对本地9.5服务器使用get
我计划时间为23.8毫秒,运行时间为0.011毫秒。你的问题出在其他地方。
答案 1 :(得分:0)
plpgsql
函数通常不提供最快的解决方案,纯SQL解决方案总是会表现得更好,所以你应该首先搜索SQL解决方案(如果你是的话,你可以创建一个sql
函数确定要将逻辑包装在函数中。)
递归CTE是您问题的典型解决方案:
with recursive path(path) as (
values ('d2140247-ef9d-4d51-ac28-ba008c378720//H%3A/files/doc/doc/doc/doc/.../doc/doc/')
),
rparents(rpath) as (
select reverse(trim(trailing '/' from path))
from path
union all
select trim(leading '/' from substring(rpath from p))
from rparents, position('/' in rpath) p
where p > 0
)
select reverse(rpath)
from rparents
但遗憾的是,从结尾处搜索字符串是不可能的,因此需要多次调用reverse()
函数来实现这种功能。
另一个解决方案是使用窗口函数:
with path(path) as (
values ('d2140247-ef9d-4d51-ac28-ba008c378720//H%3A/files/doc/doc/doc/doc/.../doc/doc/')
)
select string_agg(unnest, '/') over (order by ordinality)
from path, unnest(string_to_array(path, '/')) with ordinality
where unnest != ''
注意:with ordinality
是9.4+功能,但您可以使用子选择row_number()
进行模拟。
另外,如果你真的想得到一个父路径数组(而不是它们的结果集),你可以使用array_agg()
(可能还有一个子选择)。
这两个功能都比plpgsql
功能更好,但是如果你在问题中使用这么长的路径,由于IO,它们仍然会很慢。
编辑:一个版本,它将斜杠字符视为文件夹名称的一部分,后跟另一个斜杠:
with path(path) as (
values ('d2140247-ef9d-4d51-ac28-ba008c378720//H%3A/files/doc///doc/doc/doc/.../doc/doc/')
)
select string_agg(regexp_split_to_table, '/') over (order by ordinality)
from path, regexp_split_to_table(path, '/(?!/)') with ordinality
where regexp_split_to_table != ''