Seite 1 von 2 12 LetzteLetzte
Ergebnis 1 bis 10 von 11

Thema: bulk load über java

  1. #1
    MeisterU ist offline Neuer Benutzer
    Registriert seit
    15.03.2010
    Beiträge
    14

    Standard bulk load über java

    Hi!

    Ich benutze Postgres 8.4 mit einem JDBC4 Treiber und habe eine Frage zum Bulk Load.

    Ich suche eine von Java ausführbar Methode, um so etwas wie \copy table(column 1, column 2) from file.csv... auf ein csv File auszuführen.

    Ich erstelle aus anderen Daten normalerweise eine csv Datei und lade sie dann per \copy in die Datenbank.
    Nun soll das Programm an dem ich grade arbeite auch für Benutzer verständlich sein, die nicht auf Kommandozeilenebene ein \copy ausführen wollen/können. (Ziel: Benutzer wählt auf der GUI ein File aus. Dann wird es in Java verarbeitet und als Ergebnis ist dieses File dann in der Datenbank und das alles ohne, dass der Benutzer csv Files löschen, kopieren oder \copy machen muss)

    Nun stelle ich mir 2 Szenarien vor von denen ich nicht weiß wie ich sie effizient (also ohne das Standard INSERT) implementieren kann.

    1. Ich parse meine Daten direkt in einen Buffer und führe aus diesem Buffer (der irgendwie wie ein in Memory csv aussieht (zb. 2000 csv Zeilen)) ein copy Befehl aus. Wie kann ich das machen?

    2. Ich parse meine Daten in ein CSV File, speichere es auf der Platte und führe einen Copy Befehl über Java aus, der mir die Daten in die Datenbank lädt. Für so etwas gibt es tatsächlich den copymanager, der schiebt die csv Daten trotzdem nochmal mit einem Reader durch die JAVA VM und erst dann in die Datenbank. Diesen Schritt möchte ich verhindern, denn es ist absolut ineffizient 10GB Dateien von einem Java Reader durch die VM laufen zu lassen.


    Was denkt Ihr was am effizientesten ist? Und wie kann ich das implementieren? Ich vermute, dass Methode 1 am besten wäre, wenn implementierbar, denn dann brauche ich die CSV gar nicht auf Platte zu schreiben sondern brauche nur einen Read(vom nicht nicht geparsten File) und einem Write(direkt in die db).

    Vielen Dank schon mal für die schnellen Antworten.

    Meister U.

  2. #2
    ads
    ads ist offline Super-Moderator
    Registriert seit
    08.02.2006
    Ort
    MD
    Beiträge
    4.020

    Standard

    Du könntest dir mal den SQL-Befehl COPY ... FROM STDIN anschauen.

    Dann musst du die Daten von Java aus nur noch in die Datenbankverbindung schieben.
    Xandrian: Kurz gesagt: Du hast ein falsches Konzept und willst nicht auf ads hören

    Jetzt NEU: PostgreSQL - Datenbankpraxis für Anwender, Administratoren und Entwickler

    PostgreSQL Service & Support

  3. #3
    MeisterU ist offline Neuer Benutzer
    Registriert seit
    15.03.2010
    Beiträge
    14

    Standard

    schonmal vielen Dank.

    Aber wie schiebe ich? Der Befehl würde ja irgendwie so aussehen:

    copyManager.copyIn("COPY foo FROM stdin");

    foo ist eine Tabelle, die nur eine Spalte hat und ich würde nun gerne 1,2,3,4,5.... reinschieben. Wie mache ich das?

  4. #4
    akretschmer ist offline Super-Moderator
    Registriert seit
    29.10.2006
    Ort
    Nähe Dresden
    Beiträge
    5.337

    Standard

    Zitat Zitat von MeisterU Beitrag anzeigen
    schonmal vielen Dank.

    Aber wie schiebe ich? Der Befehl würde ja irgendwie so aussehen:

    copyManager.copyIn("COPY foo FROM stdin");

    foo ist eine Tabelle, die nur eine Spalte hat und ich würde nun gerne 1,2,3,4,5.... reinschieben. Wie mache ich das?
    Wenn es nur darim geht, eine einspaltige Tabelle mit fortlaufenden Zahlen zu füllen, dann geht das trivial einfacher so:

    Code:
    test=# create table schiebe (i int);
    CREATE TABLE
    test=# insert into schiebe select generate_Series(1,10);
    INSERT 0 10
    test=# select * from schiebe;
     i
    ----
      1
      2
      3
      4
      5
      6
      7
      8
      9
     10
    (10 rows)
    Es bleibt nun die Frage, wozu man sowas machen will, wenn es generate_series() gibt. Dies macht so eine Tabelle ganz, ganz sicher überflüssig.


    Andreas
    --
    ads Das hatte dir akretschmer gestern schon gesagt und siehe da sobald du das machst, funktioniert es ;-)
    https://www.xing.com/profile/Andreas_Kretschmer7

  5. #5
    MeisterU ist offline Neuer Benutzer
    Registriert seit
    15.03.2010
    Beiträge
    14

    Standard

    Hi!

    Ich will mit diesem einfachen Beispiel einfach mal den COPY Operator über Java testen. Sobald ich das verstehe, werden natürlich andere/komplexere Daten eingefügt.

  6. #6
    ads
    ads ist offline Super-Moderator
    Registriert seit
    08.02.2006
    Ort
    MD
    Beiträge
    4.020

    Standard

    Keine Ahnung, wie man in Java direkt in einen Stream schreibt. Steht aber sicher irgendwo in der Dokumentation.

    Wenn du etwas findest, füge doch bitte deine Fundstellen hier ein. Damit andere in Zukunft etwas davon haben.
    Xandrian: Kurz gesagt: Du hast ein falsches Konzept und willst nicht auf ads hören

    Jetzt NEU: PostgreSQL - Datenbankpraxis für Anwender, Administratoren und Entwickler

    PostgreSQL Service & Support

  7. #7
    MeisterU ist offline Neuer Benutzer
    Registriert seit
    15.03.2010
    Beiträge
    14

    Standard

    Es gibt den CopyManager CopyManager

    Mit diesem wird eine Methode copyIn anwendbar.

    copyIn(sql, stream)
    copyIn(sql, Reader)

    Ich habe jetzt so "gelöst":
    Connection connection = DriverManager.getConnection(*,*,*);
    PGConnection pConn = (PGConnection)connection;
    CopyManager copyManager = pConn.getCopyAPI();
    copyManager.copyIn("COPY bla FROM stdin", new FileReader(new File("file.txt")));

    Nun ergeben sich 2 Probleme:

    1. Ich muss immernoch zuerst ein CSV File schreiben und kann nicht wirklich vom Parser direkt in die DB parsen und
    2. bekomme ich jetzt Fehler wie: "COPY-Ende-Markierung verfälscht" oder "ungültige Byte-Sequenz für Kodierung »UTF8«: 0x00
    Hinweis: Dieser Fehler kann auch auftreten, wenn die Bytesequenz nicht mit der Kodierung übereinstimmt, die der Server erwartet, welche durch »client_encoding« bestimmt wird."
    je nachdem ob ich ein \. am Ende mache oder nicht.

    Ich vermute, dass ich ein spezielles CharSet mit Java benutzen muss. Oder gibt es weitere Ideen?

  8. #8
    akretschmer ist offline Super-Moderator
    Registriert seit
    29.10.2006
    Ort
    Nähe Dresden
    Beiträge
    5.337

    Standard

    Zitat Zitat von MeisterU Beitrag anzeigen
    2. bekomme ich jetzt Fehler wie: "COPY-Ende-Markierung verfälscht" oder "ungültige Byte-Sequenz für Kodierung »UTF8«: 0x00
    Hinweis: Dieser Fehler kann auch auftreten, wenn die Bytesequenz nicht mit der Kodierung übereinstimmt, die der Server erwartet, welche durch »client_encoding« bestimmt wird."
    je nachdem ob ich ein \. am Ende mache oder nicht.

    Ich vermute, dass ich ein spezielles CharSet mit Java benutzen muss. Oder gibt es weitere Ideen?
    Deine Daten passen nicht zu UTF8.

    select * from depesz; » Blog Archive » ERROR: invalid byte sequence for encoding

    Andreas
    --
    ads Das hatte dir akretschmer gestern schon gesagt und siehe da sobald du das machst, funktioniert es ;-)
    https://www.xing.com/profile/Andreas_Kretschmer7

  9. #9
    MeisterU ist offline Neuer Benutzer
    Registriert seit
    15.03.2010
    Beiträge
    14

    Standard

    eine andere, viel trivialere Frage habe ich dann noch

    ich habe

    dbtest=# copy bla from 'bla.txt';
    FEHLER: konnte Datei »bla.txt« nicht zum Lesen öffnen: No such file or directory

    aber

    dbtest=# \copy bla from bla.txt

    das läuft ohne Probleme. Den Befehl \copy kann ich von Java aus aber nicht anschieben, lediglich copy. Wo liegt also, dass Problem, dass ein Befehl die Datei findet, die andere aber nicht?

    Bzw warum brauch ich den totalen und nicht den relativen Pfad?
    Geändert von MeisterU (16.03.2010 um 14:31 Uhr)

  10. #10
    akretschmer ist offline Super-Moderator
    Registriert seit
    29.10.2006
    Ort
    Nähe Dresden
    Beiträge
    5.337

    Standard

    Zitat Zitat von MeisterU Beitrag anzeigen
    eine andere, viel trivialere Frage habe ich dann noch

    ich habe

    dbtest=# copy bla from 'bla.txt';
    FEHLER: konnte Datei »bla.txt« nicht zum Lesen öffnen: No such file or directory

    aber

    dbtest=# \copy bla from bla.txt

    das läuft ohne Probleme. Den Befehl \copy kann ich von Java aus aber nicht anschieben, lediglich copy. Wo liegt also, dass Problem, dass ein Befehl die Datei findet, die andere aber nicht?
    Das eine arbeitet auf dem Server und das andere auf dem Client.

    Code:
    Command:     COPY
    Description: copy data between a file and a table
    
    
    -- versus
    
    Input/Output
      \copy ...              perform SQL COPY with data stream to the client host

    Andreas
    --
    ads Das hatte dir akretschmer gestern schon gesagt und siehe da sobald du das machst, funktioniert es ;-)
    https://www.xing.com/profile/Andreas_Kretschmer7

Seite 1 von 2 12 LetzteLetzte

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •  

Links: Tobias Bauer - IT- und Funkdienstleistungen   -   Bilderrahmen-kaufen.de - Der Onlineshop für Bilderrahmen & Fotorahmen   -   Funkforum