2015-11-12 165 views
1

我想用我的postgres服務器也提供我不想存儲在數據庫中的文檔和圖像,原因有幾個。Postgres讀取和寫入外部文件

沒有爲這一目的https://github.com/darold/external_fileexternal fileexternal file的延伸和改變了代碼一點,以滿足我的需求,在不改變核心(見下文)。我使用9.5作爲我希望這個版本是決賽前我完成開發;-)

我會遇到以下問題:

  • 寫作工作快速,似乎是可靠的,但大文件導致出內存(1Gig及以上)。
  • 閱讀經常掛起很長時間(選擇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; 

解釋我需要上面的:這將是一個醫療系統,該系統還通過不安全的連接服務,存儲巨大documens和圖像的一部分。將數百GB存儲在數據庫中對我來說似乎不是個好主意。由於它們不會改變,只需添加新的文檔,文件的備份就更容易了。由於數據庫已經處理了SSL連接,因此不必部署額外的sftp服務器來提供這些文件!

回答

0

你的理念註定要失敗。您正在使用數據庫服務器作爲大文件磁盤操作的緩存。這顯然浪費了時間和資源,因爲服務器每次都必須保存文件的全部內容以暫時刪除它。

在我看來,使用ftp服務器會更簡單,更自然,效率更高的解決方案。

+0

我只想讀取和寫入我也可以存儲在數據庫中的文件 - 而不是它們駐留在服務器文件系統中。我不明白爲什麼數據庫服務器不應該爲此服務,同時我使用SQL數據庫來處理那些有意​​義的事情。正如我所說的那樣,如果我不需要部署和配置額外的sftp或ftps服務器,這將使部署我的系統變得更加容易。 – MichaSchumann

+0

不是*而是**另外**。事實上,現在你的模型是:1.將大文件存儲在數據庫中('lowrite'),2.將它保存到文件('lo_export'),3.從數據庫中移除它('lo_unlink')。這個不成立。它涉及大量不必要的昂貴的數據庫操作,包括預寫日誌。 – klin

+0

這個我可以理解,所以這個方法真的是無稽之談,我並沒有真正理解這兩個函數的來源,因爲我對Postgres相當陌生。如果我能夠「傳遞」二進制文件並且不會觸及數據庫,那將是非常棒的。就像數據包裝器,但我沒有找到一個二進制文件,如圖像和壓縮文件。謝謝你的解釋! – MichaSchumann