Problem PL/Python-Stored Procedure und BYTEA
Hallo miteinander!
Ich bin neu hier und hoffe, dass ich mich mit meinem Problem hier an die =
richtige Mailing-Liste wenden.
Ich bastle seit einiger Zeit schon an einer Bilder-Datenbank. Die Bilder =
liegen dabei auf dem Filesystem, die Meta-Informationen (Beschreibung des=
Bildes usw...) dazu werden in einer PostgreSQL-Datenbank gespeichert. Da=
ich gerne das Benutzer-Management von PostgreSQL nutzen möchte, sieht =
mein Ziel so aus:
Auf das Bilderverzeichnis im Filesystem soll nur der Benutzer "postgres" =
Zugriff haben, sprich ein normaler Systembenutzer (ich benutze Ubunut Lin=
ux) soll keine Möglichkeit haben, da manuell hinein zu kommen.
Wenn ein User meiner Bilder-Datenbank (erhält einen stark eingeschrän=
ken PostgreSQL-Account) von der Datenbank her die Rechte hat, ein Bild ei=
nzusehen, soll er es von PostgreSQL "durchgereicht" bekommen.
Den Zugriff auf das Dateisystem für PostgreSQL habe ich mit Stored Proc=
edures in Python realisiert, Rückgabe-Typ ist BYTEA.
Meine erste Version sah so aus:
####
CREATE FUNCTION read_file(TEXT) RETURNS BYTEA AS '
import os
path =3D args[0].replace(''/'', os.sep)
# öffne Datei im binären Lese-Modus
fp =3D open(path, "rb", 0)
ret =3D fp.read()
fp.close()
return ret
' LANGUAGE plpythonu;
#####
Das Problem war hier dass die Rückgabe offenbar nicht escaped war, und =
so immer nur ca. 4 Byte durchgereicht wurden. Nach einiger Recherche habe=
ich ein Stück Python-Code gefunden, welches die Rückgabe präparier=
t hat:
####
CREATE FUNCTION read_file2(TEXT) RETURNS BYTEA AS '
import os
path =3D args[0].replace(''/'', os.sep)
# öffne Datei im binären Lese-Modus
fp =3D open(path, "rb", 0)
ret =3D fp.read()
fp.close()
# escape String
return ''.join(['\\%03o' % ord(x) for x in ret])
' LANGUAGE plpythonu;
#####
Damit hat es theoretisch schon mal geklappt: Ich konnte über einen Aufr=
uf dieser Stored Procedure mittels eines Java-Programmes (JDBC) die Binä=
rdaten eines Bildes auslesen, mit dem Java-Programm wieder zurück in ei=
ne Datei schreiben und hatte damit eine Kopie des Bildes.
So, nach dieser langen Ausschweifung nun mein eigentliches Problem:
Nach dem die Sache mit einem Bild geklappt hat, hat mich wohl der Große=
nwahn gepackt und ich dachte mir, dass ich ja vielleicht nicht nur Bilder=
, sondern generell Media-Daten, also auch Videos etc... über meine Date=
nbank verwalten könnte. Also habe ich mal eine ca. 40 MB große Datei =
über diesen Weg kopieren wollen.
Das Resultat war, dass meine Festplatte angefangen hat wie wild zu röde=
ln und mein komplettes System unerträglich langsam wurde. Ich konnte ni=
cht mal mehr ne Shell öffnen um den Prozess abzuschießen. Nach mind. =
5 Minuten hab ich meinen Computer dann neugestartet. Dann hab ich mich ma=
l mit immer großer werdenden Dateien vorgetastet. So bis ca. 10 MB konn=
te ich eine Datei auf diesem Wege kopieren, danach ging die Rödelei dan=
n wieder los.
Aber irgendwie kann ich mir es nicht vorstellen, dass man auf diesem Wege=
maximal 10 MB durch das DBMS reichen kann. Ich habe den Verdacht dass da=
s Escapen der Rückgabe in Python die Probleme bereitet, aber sicher bin=
ich mir nicht.
Hat sich vielleicht jemand anderes schon mit =C4hnlichem beschäftigt un=
d kann mir einen Tipp geben, wie ich das anders lösen könnte?
Ich würde eigentlich gerne bei Python als PL bleiben, weil es da eine s=
ehr einfache Bibliothek gibt, mit der ich Thumbnails von Bildern erzeugen=
kann (was ich gerne hätte).
Würde mich sehr freuen, wenn mir jemand helfen könnte! :)
Danke für eure Aufmerksamkeit & Gruß,
Tim
--
Der GMX SmartSurfer hilft bis zu 70% Ihrer Onlinekosten zu sparen!
Ideal für Modem und ISDN: http://www.gmx.net/de/go/smartsurfer
---------------------------(end of broadcast)---------------------------
TIP 7: You can help support the PostgreSQL project by donating at
http://www.postgresql.org/about/donate
Re: Problem PL/Python-Stored Procedure und BYTEA
> Den Zugriff auf das Dateisystem für PostgreSQL habe ich mit
> Stored Procedures in Python realisiert, Rückgabe-Typ ist BYTEA.
>
> Das Problem war hier dass die Rückgabe offenbar nicht escaped
> war, und so immer nur ca. 4 Byte durchgereicht wurden. Nach
> einiger Recherche habe ich ein Stück Python-Code gefunden,
> welches die Rückgabe präpariert hat:
>
> ####
> CREATE FUNCTION read_file2(TEXT) RETURNS BYTEA AS '
> import os
> path =3D args[0].replace(''/'', os.sep)
> # öffne Datei im binären Lese-Modus
> fp =3D open(path, "rb", 0)
> ret =3D fp.read()
> fp.close()
> # escape String
> return ''.join(['\\%03o' % ord(x) for x in ret])
> ' LANGUAGE plpythonu;
> #####
>
> Damit hat es theoretisch schon mal geklappt: Ich konnte über
> einen Aufruf dieser Stored Procedure mittels eines
> Java-Programmes (JDBC) die Binärdaten eines Bildes auslesen,
> mit dem Java-Programm wieder zurück in eine Datei schreiben
> und hatte damit eine Kopie des Bildes.
>
> So, nach dieser langen Ausschweifung nun mein eigentliches Problem:
> Nach dem die Sache mit einem Bild geklappt hat, hat mich wohl
> der Großenwahn gepackt und ich dachte mir, dass ich ja
> vielleicht nicht nur Bilder, sondern generell Media-Daten,
> also auch Videos etc... über meine Datenbank verwalten
> könnte. Also habe ich mal eine ca. 40 MB große Datei über
> diesen Weg kopieren wollen.
> Das Resultat war, dass meine Festplatte angefangen hat wie
> wild zu rödeln und mein komplettes System unerträglich
> langsam wurde. Ich konnte nicht mal mehr ne Shell öffnen um
> den Prozess abzuschießen. Nach mind. 5 Minuten hab ich meinen
> Computer dann neugestartet. Dann hab ich mich mal mit immer
> großer werdenden Dateien vorgetastet. So bis ca. 10 MB konnte
> ich eine Datei auf diesem Wege kopieren, danach ging die
> Rödelei dann wieder los.
Erstens: Das CREATE FUNCTION-Statement, so wie es oben steht, ist
syntaktisch falsch - offenbar wurden in der 'return'-Zeile die
einfachen Hochkommata nicht verdoppelt.
Ein guter Grund, für die Funktionsdefinition $$<programmtext>$$
zu verwenden.
Ich habe die Funktion bei mir angelegt, und sie funktioniert
grundsätzlich.
Das beobachtete Problem kommt sicher vom Speicherverbrauch: die
ganze Datei wird in den Hauptspeicher geladen und als String bearbeitet.
Das System ist sicher deshalb gestorben, weil kein Hauptspeicher
mehr frei war und wahrscheinlich wie verrückt ge'page't wurde.
Mein System ist RedHat Linux auf Intel Xeon, Kernel 2.4.21-40.ELsmp,
3GB RAM, 2GB Swap, 4 Prozessoren (angezeigt).
Ich habe eine 1GB große Datei angelegt und es ausprobiert.
Der postmaster hat einen Prozessor zugemacht, der Memoryverbrauch dieses
Prozesses stieg gemütlich auf 60% (vom physischen Hauptspeicher, also etwa
2GB), dann kam
ERROR: plpython: function "read_file2" failed
DETAIL: exceptions.MemoryError:
Spricht für sich.
Einen zweiten Versuch mit einem 100MB großen File habe ich abgebrochen, a=
ls
70% Memory belegt waren und die Maschine bereits heftig swapte.
Wahrscheinlich ist Python (mit dem ich mich nicht auskenne) memoryhungrig,
vielleicht ist es auch ein Problem von PostgreSQL.
Vielleicht läßt sich die Funktion so schreiben, daß sie Memory spart?
Liebe Grüße,
Laurenz Albe
---------------------------(end of broadcast)---------------------------
TIP 6: explain analyze is your friend
Re: Problem PL/Python-Stored Procedure und BYTEA
Am Mittwoch, 8. November 2006 09:49 schrieb Tim Frießinger:
> Nach dem die Sache mit einem Bild geklappt hat, hat mich wohl der
> Großenwahn gepackt und ich dachte mir, dass ich ja vielleicht nicht n=
ur
> Bilder, sondern generell Media-Daten, also auch Videos etc... über me=
ine
> Datenbank verwalten könnte. Also habe ich mal eine ca. 40 MB große =
Datei
> über diesen Weg kopieren wollen. Das Resultat war, dass meine Festpla=
tte
> angefangen hat wie wild zu rödeln und mein komplettes System unerträ=
glich
> langsam wurde.
Ich kenne zwar die Interna von Python nicht, aber ich kann mir gut ausmal=
en,
wie bei einer solchen Implementierung die ganze Datei etwa drei bis sechs=
Mal
im Speicher kopiert wird. Am effizientesten wird das, wenn man die Daten=
als
bytea in der Datenbank speichert und im binären Protokollmodus abruft. =
Dann
hat man maximal eine Kopie im Speicher.
--
Peter Eisentraut
http://developer.postgresql.org/~petere/
---------------------------(end of broadcast)---------------------------
TIP 9: In versions below 8.0, the planner will ignore your desire to
choose an index scan if your joining column's datatypes do not
match
Re: Problem PL/Python-Stored Procedure und BYTEA
Hallo und vielen Dank für die schnelle Antwort!
> Ich kenne zwar die Interna von Python nicht, aber ich kann mir gut
> ausmalen,
> wie bei einer solchen Implementierung die ganze Datei etwa drei bis sec=
hs
> Mal
> im Speicher kopiert wird. Am effizientesten wird das, wenn man die Dat=
en
> als
> bytea in der Datenbank speichert und im binären Protokollmodus abruft=
..
> Dann
> hat man maximal eine Kopie im Speicher.
Ursprünglich hatte ich das auch so vor, dass ich die Bilder meiner Bild=
er-Datenbank direkt als BYTEA in der Datenbank ablege. Ich bin dann aber =
von der Idee abgekommen, da ich es ganz praktisch finde, wenn die ganzen =
Bilderdateien weiterhin direkt im Filesystem verfügbar sind und man (zu=
mindest als root) auch direkt an die Bilder rankommt, ohne den Umweg üb=
er die Datenbank zu machen. Kategorien und Alben welche man in meiner Bil=
derdatenbank anlegt, werden durch Stored Procedures auch direkt ins Files=
ystem übertragen, dieses Prinzip würde ich gerne beibehalten.
Vielleicht gelingt es mir ja noch eine bessere Escape-Möglichkeit zu fi=
nden, welche nicht so Speicherhungrig ist und das System "tot-swappen" tu=
t.
Danke & Gruß,
Tim Frießinger
--
Der GMX SmartSurfer hilft bis zu 70% Ihrer Onlinekosten zu sparen!
Ideal für Modem und ISDN: http://www.gmx.net/de/go/smartsurfer
---------------------------(end of broadcast)---------------------------
TIP 2: Don't 'kill -9' the postmaster
Re: Problem PL/Python-Stored Procedure und BYTEA
> Ursprünglich hatte ich das auch so vor, dass ich die Bilder
> meiner Bilder-Datenbank direkt als BYTEA in der Datenbank
> ablege. Ich bin dann aber von der Idee abgekommen, da ich es
> ganz praktisch finde, wenn die ganzen Bilderdateien weiterhin
> direkt im Filesystem verfügbar sind und man (zumindest als
> root) auch direkt an die Bilder rankommt, ohne den Umweg über
> die Datenbank zu machen. Kategorien und Alben welche man in
> meiner Bilderdatenbank anlegt, werden durch Stored Procedures
> auch direkt ins Filesystem übertragen, dieses Prinzip würde
> ich gerne beibehalten.
> Vielleicht gelingt es mir ja noch eine bessere
> Escape-Möglichkeit zu finden, welche nicht so Speicherhungrig
> ist und das System "tot-swappen" tut.
Vielleicht ist es ja eine Möglichkeit, die Funktion irgendwie
effizienter zu schreiben, vielleicht in C. Einfach eine binäre Datei
lesen und ausgeben, das sollte ja nicht so schwierig sein.
Oder die Datei in Stücken zu lesen und die dann mit || zusammenzufügen.
Liebe Grüße,
Laurenz Albe
---------------------------(end of broadcast)---------------------------
TIP 9: In versions below 8.0, the planner will ignore your desire to
choose an index scan if your joining column's datatypes do not
match