出于多种原因,我还想使用我的 postgres 服务器来提供我不想存储在数据库中的文档和图像。
为此目的有一个扩展 https://github.com/darold/external_file external file external file并在不更改核心的情况下稍微更改了代码以满足我的需求(见下文)。我正在使用 9.5,因为我希望这个版本在我完成开发之前是最终版本 ;-)
我遇到了以下问题:
- 写入速度很快而且似乎很可靠,但大文件会导致内存不足(1G 及以上)。
- 读取经常挂起或挂起很长时间(select readEFile('aPath');)并且不可靠。
- 尽管不涉及数据库表,但 WAL 和数据库的大小都在快速增长。
我的问题:
下面的代码有什么问题?我如何从 WAL 中排除所有这些操作?有没有人已经写过类似的东西并愿意分享他的发展?
CREATE OR REPLACE FUNCTION public.writeefile(
buffer bytea,
filename character varying)
RETURNS void AS
$BODY$
DECLARE
l_oid oid;
lfd integer;
lsize integer;
BEGIN
l_oid := lo_create(0);
lfd := lo_open(l_oid,131072); --0x00020000 write mode
lsize := lowrite(lfd,buffer);
PERFORM lo_close(lfd);
PERFORM lo_export(l_oid,filename);
PERFORM lo_unlink(l_oid);
END;
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
ALTER FUNCTION public.writeefile(bytea, character varying)
OWNER TO itcms;
CREATE OR REPLACE FUNCTION public.readefile(filename character varying)
RETURNS bytea AS
$BODY$
DECLARE
l_oid oid;
r record;
buffer bytea;
BEGIN
buffer := '';
SELECT lo_import(filename) INTO l_oid;
FOR r IN ( SELECT data
FROM pg_largeobject
WHERE loid = l_oid
ORDER BY pageno ) LOOP
buffer = buffer || r.data;
END LOOP;
PERFORM lo_unlink(l_oid);
return buffer;
END;
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
ALTER FUNCTION public.readefile(character varying)
OWNER TO itcms;
解释我对上述内容的需求:这将是医疗系统的一部分,该系统还通过不安全的连接提供和存储大量文档和图像。在数据库中存储数百 GB 对我来说似乎不是一个好主意。由于它们不会更改并且只是添加了新文档,因此文件备份要容易得多。由于数据库已经处理 SSL 连接,因此不必部署额外的 sftp 服务器来为这些文件提供服务会很棒!
最佳答案
你的想法注定要失败。您正在使用数据库服务器作为对大文件进行磁盘操作的缓存。这显然是对时间和资源的浪费,因为服务器每次都必须保存文件的全部内容才能将其暂时删除。
在我看来,使用 ftp 服务器将是更简单、更自然且效率更高的解决方案。
关于postgresql - Postgres读写外部文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33668412/