RAM verbrauchsproblem Postgresql+ZEOS

Für Themen zu Datenbanken und Zugriff auf diese. Auch für Datenbankkomponenten.
Dragon
Beiträge: 162
Registriert: Mi 31. Jul 2013, 15:07
OS, Lazarus, FPC: Ubuntu 16.04, CodeTyphon 5.80

Re: RAM verbrauchsproblem Postgresql+ZEOS

Beitrag von Dragon »

af0815: ich habe auch mit mehr daten probiert und wenn dann der verbrauch zumbeispiel bei 25MB text auf 1-1.5GB steigt wird das schonmal problematisch bei 4GB ram

Benutzeravatar
af0815
Lazarusforum e. V.
Beiträge: 6198
Registriert: So 7. Jan 2007, 10:20
OS, Lazarus, FPC: FPC fixes Lazarus fixes per fpcupdeluxe (win,linux,raspi)
CPU-Target: 32Bit (64Bit)
Wohnort: Burgenland
Kontaktdaten:

Re: RAM verbrauchsproblem Postgresql+ZEOS

Beitrag von af0815 »

Ok, wenn so zunimmt schon :-)

Kann man das Problem in eine Beispielprojekt stecken ? Ich sehe mir es gerne mal an (mit sqlite), klingt irgendwie interessant.

Andreas
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).

wp_xyz
Beiträge: 4869
Registriert: Fr 8. Apr 2011, 09:01

Re: RAM verbrauchsproblem Postgresql+ZEOS

Beitrag von wp_xyz »

Was passiert eigentlich sonst noch in der Anwendung? Wir hatten hier immer wieder den Fall, dass harmloser Code gezeigt wurde, aber Hund ganz wo anders begraben war.

Dragon
Beiträge: 162
Registriert: Mi 31. Jul 2013, 15:07
OS, Lazarus, FPC: Ubuntu 16.04, CodeTyphon 5.80

Re: RAM verbrauchsproblem Postgresql+ZEOS

Beitrag von Dragon »

ich habe den gesamten code eine seite vorher gepostet den SQLite code den ich benutzt habe.
Habe wies da steht die Lazaruskomponente verwendet nicht ZEOS , ZEOS hatte ich nur bei den POstgresql tests verwendet

aber hier nochmal der aktuelle code aber kein ZEOS benutzt wie gesagt

Code: Alles auswählen

procedure TForm1.Button1Click(Sender: TObject);
var
  i: qword;
  Origin: string;
  sl: TStringList;
begin
  SQLite3Connection1.DatabaseName := './DB.sqlite';
  SQLTransaction1.Database := SQLite3Connection1;
  SQLite3Connection1.Open;
  if SQLite3Connection1.Connected then
    Form1.Caption := 'Verbindung hergestellt';
  SQLQuery1.Transaction := SQLTransaction1;
 
  //Erzeugt Wörterbuchliste
  SQLQuery1.SQL.Text := 'CREATE TABLE IF NOT EXISTS tblDictonary (ID INTEGER Primary KEY, Wort VARCHAR(255) UNIQUE ON CONFLICT IGNORE);';
  SQLQuery1.ExecSQL;
  SQLTransaction1.commit;
 
 
  Origin := Loadfile('./test');
  Origin := Stringreplace(Origin, '"', '', [rfReplaceAll]);
  sl := TStringList.Create;
  sl.Delimiter := ' ';
  sl.QuoteChar := #$0;
  sl.DelimitedText := Origin;
  SQLQUERY1.Close;
  for i := 0 to sl.Count - 1 do
  begin
    SQLQuery1.SQL.Text := 'INSERT INTO tblDictonary (Wort) VALUES ("' + sl[i] + '")';
    SqlQuery1.ExecSQL;
    //SqlTransaction1.Commit;
     if i mod 1000 = 0 then
     begin
       SqlTransaction1.Commit;
       Form1.Caption := IntToStr(i);
     end;
  end;
  SQLQuery1.Close;
end;


sonst passiert nix mehr habe nur zwei buttons einmal der SQLite testcode einmal der Postgresql code weil ich zum ersten mal eine Datenbankanbindung baue

Benutzeravatar
af0815
Lazarusforum e. V.
Beiträge: 6198
Registriert: So 7. Jan 2007, 10:20
OS, Lazarus, FPC: FPC fixes Lazarus fixes per fpcupdeluxe (win,linux,raspi)
CPU-Target: 32Bit (64Bit)
Wohnort: Burgenland
Kontaktdaten:

Re: RAM verbrauchsproblem Postgresql+ZEOS

Beitrag von af0815 »

Wie groß sind die Strings die du da einliest, bzw wie sehen die Strings in etwa aus.

Wenn dein Code so einfach ist, dann hätte ich ihn mit den Beispieldaten gezippt und hier hochgeladen
Zuletzt geändert von af0815 am Sa 29. Okt 2016, 20:42, insgesamt 1-mal geändert.
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).

Dragon
Beiträge: 162
Registriert: Mi 31. Jul 2013, 15:07
OS, Lazarus, FPC: Ubuntu 16.04, CodeTyphon 5.80

Re: RAM verbrauchsproblem Postgresql+ZEOS

Beitrag von Dragon »

der inputstring ist einfach eine textdatei die textdatei (die kleine) die ich zum testen genommen habe hatte ich verlinkt eine seite vorher. Die große ist auch einfach ein standarttext einfach nur größer ca 25MB

Benutzeravatar
af0815
Lazarusforum e. V.
Beiträge: 6198
Registriert: So 7. Jan 2007, 10:20
OS, Lazarus, FPC: FPC fixes Lazarus fixes per fpcupdeluxe (win,linux,raspi)
CPU-Target: 32Bit (64Bit)
Wohnort: Burgenland
Kontaktdaten:

Re: RAM verbrauchsproblem Postgresql+ZEOS

Beitrag von af0815 »

Kannst du sagen wie lange in Zeichen die einzelnen Strings sind. Kannst ja notfalls ein Paar hier als Beispiel posten
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).

Dragon
Beiträge: 162
Registriert: Mi 31. Jul 2013, 15:07
OS, Lazarus, FPC: Ubuntu 16.04, CodeTyphon 5.80

Re: RAM verbrauchsproblem Postgresql+ZEOS

Beitrag von Dragon »

ich schmeiß einfach ein text rein und delimite bei jedem space und lese die wörter anschliesend wie zu sehen eins nach dem anderen ein um so ein wörterbuch zu erhalten

Benutzeravatar
af0815
Lazarusforum e. V.
Beiträge: 6198
Registriert: So 7. Jan 2007, 10:20
OS, Lazarus, FPC: FPC fixes Lazarus fixes per fpcupdeluxe (win,linux,raspi)
CPU-Target: 32Bit (64Bit)
Wohnort: Burgenland
Kontaktdaten:

Re: RAM verbrauchsproblem Postgresql+ZEOS

Beitrag von af0815 »

Ok, hab den Text jetzt gefunden, beim Scollen überlesen. Baue mir mal ein Programm dazu. Aktuell unter Windows 10, weil ich gerade auf der Maschine arbeite.
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).

Dragon
Beiträge: 162
Registriert: Mi 31. Jul 2013, 15:07
OS, Lazarus, FPC: Ubuntu 16.04, CodeTyphon 5.80

Re: RAM verbrauchsproblem Postgresql+ZEOS

Beitrag von Dragon »

Mit dem kleinen testtext hatte ich 75MB ram verbrauch explodieren tut er erst später bei größerem input.
Und nach dem freigeben immernoch 40MB
vor dem start der befüllung ca 13MB

Benutzeravatar
af0815
Lazarusforum e. V.
Beiträge: 6198
Registriert: So 7. Jan 2007, 10:20
OS, Lazarus, FPC: FPC fixes Lazarus fixes per fpcupdeluxe (win,linux,raspi)
CPU-Target: 32Bit (64Bit)
Wohnort: Burgenland
Kontaktdaten:

Re: RAM verbrauchsproblem Postgresql+ZEOS

Beitrag von af0815 »

So wie ich es mir gedacht habe, du hast noch ander Funktionen benutzt
wo ist die Loadfile('./test') ?

Das ist genau der Grund warum nach einem KOMPLETTEN Beispielcode verlangt wird - damit der Code vollständig ist und man nicht unnötig hersuchen und schreiben muss, wenn man sich schon ein Problem von wem ansehen will/möchte.
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).

Dragon
Beiträge: 162
Registriert: Mi 31. Jul 2013, 15:07
OS, Lazarus, FPC: Ubuntu 16.04, CodeTyphon 5.80

Re: RAM verbrauchsproblem Postgresql+ZEOS

Beitrag von Dragon »

komplett

Code: Alles auswählen

unit Unit1;
 
{$mode objfpc}{$H+}
 
interface
 
uses
  Classes, SysUtils, sqldb, DB, sqlite3conn, FileUtil, ZConnection, ZDataset,
  Forms, Controls, Graphics, Dialogs, StdCtrls;
 
type
 
  { TForm1 }
 
  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    DataSource1: TDataSource;
    ListBox1: TListBox;
    SQLite3Connection1: TSQLite3Connection;
    SQLQuery1: TSQLQuery;
    SQLTransaction1: TSQLTransaction;
    ZConnection1: TZConnection;
    ZQuery1: TZQuery;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private
    { private declarations }
  public
    { public declarations }
  end;
 
var
  Form1: TForm1;
 
implementation
 
//Quelle entwicklerecke
function LoadFile(FilePath: string): string;
var
  fm: tfilestream;
  s: string;
begin
  fm := tfilestream.Create(FilePath, fmopenread);
  setlength(s, fm.size);
  fm.Read(s[1], fm.size);
  fm.Free;
  Result := s;
  s := '';
end;
//----
{$R *.lfm}
 
{ TForm1 }
procedure TForm1.Button1Click(Sender: TObject);
var
  i: qword;
  Origin: string;
  sl: TStringList;
begin
  SQLite3Connection1.DatabaseName := './DB.sqlite';
  SQLTransaction1.Database := SQLite3Connection1;
  SQLite3Connection1.Open;
  if SQLite3Connection1.Connected then
    Form1.Caption := 'Verbindung hergestellt';
  SQLQuery1.Transaction := SQLTransaction1;
 
  //Erzeugt Wörterbuchliste
  SQLQuery1.SQL.Text := 'CREATE TABLE IF NOT EXISTS tblDictonary (ID INTEGER Primary KEY, Wort VARCHAR(512) UNIQUE ON CONFLICT IGNORE);';
  SQLQuery1.ExecSQL;
  SQLTransaction1.commit;
 
  Origin := Loadfile('./White_Fang');
  Origin := Stringreplace(Origin, '"', '', [rfReplaceAll]);
  sl := TStringList.Create;
  sl.Delimiter := ' ';          // Leerzeichen als Wort Trenner
  sl.QuoteChar := #$0;          // keine " als Maskierung
  sl.DelimitedText := Origin;   
 
  //Daten in Wörterbuch eintrag
  SQLQUERY1.Close;
  for i := 0 to sl.Count - 1 do
  begin
    SQLQuery1.SQL.Text := 'INSERT INTO tblDictonary (Wort) VALUES ("' + sl[i] + '")';
    SqlQuery1.ExecSQL;
    if i mod 1500 = 0 then
    begin
      SqlTransaction1.Commit;
      SQLQuery1.Clear;
      Form1.Caption := IntToStr(i);
    end;
 
  end;
  SQLite3Connection1.Free
end;
 
procedure TForm1.Button2Click(Sender: TObject);
var
  i: qword;
  Origin: string;
  sl: TStringList;
begin
  ZQuery1.Close();
  ZQuery1.SQL.Clear;
  try
    ZQuery1.SQL.Add('SELECT * FROM dict LIMIT 1;');
  except
    ZQuery1.SQL.Add('CREATE TABLE IF NOT EXISTS dict ( id SERIAL PRIMARY KEY , word varchar(512) NOT NULL);');
    ZQuery1.SQL.Add(
      'CREATE TABLE IF NOT EXISTS stats ( w1 INTEGER NOT NULL REFERENCES dict(id), w2 INTEGER NOT NULL REFERENCES dict(id), fw INTEGER NOT NULL REFERENCES dict(id), az INTEGER NOT NULL, PRIMARY KEY (w1, w2, fw));');
    ZQuery1.SQL.Add('CREATE UNIQUE INDEX ON dict(word);');
  end;
 
  ZQuery1.Open;
  ZQuery1.ExecSQL;
 
 
  Origin := Loadfile('./White_Fang');
  Origin := Stringreplace(Origin, '''', '''' + '''', [rfReplaceAll]);
  sl := TStringList.Create;
  sl.Delimiter := ' ';
  sl.QuoteChar := #$0;
  sl.DelimitedText := Origin;
  for i := 0 to sl.Count - 1 do
  begin
    //ZQuery1.SQL.Clear;
    //ZQuery1.SQL.Add('INSERT INTO dict (word) VALUES (''' + sl[i] + ''') ON CONFLICT DO NOTHING;');
    //ZQuery1.ExecSQL;
 
    ZQuery1.SQL.Text := 'INSERT INTO dict (word) VALUES (''' + sl[i] + ''') ON CONFLICT DO NOTHING;';
    ZQuery1.ExecSQL;
    if i mod 1000 = 0 then
    begin
      ZConnection1.Commit;
      Form1.Caption := IntToStr(i);
    end;
  end;
  sl.Free;
end;
 
end.

Benutzeravatar
af0815
Lazarusforum e. V.
Beiträge: 6198
Registriert: So 7. Jan 2007, 10:20
OS, Lazarus, FPC: FPC fixes Lazarus fixes per fpcupdeluxe (win,linux,raspi)
CPU-Target: 32Bit (64Bit)
Wohnort: Burgenland
Kontaktdaten:

Re: RAM verbrauchsproblem Postgresql+ZEOS

Beitrag von af0815 »

Geht so schneller mit sqlite

Code: Alles auswählen

 
  Origin := Loadfile('./test.txt');
  Origin := Stringreplace(Origin, '"', '', [rfReplaceAll]);
  sl := TStringList.Create;
  sl.Delimiter := ' ';
  sl.QuoteChar := #$0;
  sl.DelimitedText := Origin;
  SQLQuery1.Close;
  SQLQuery1.Params.Clear;
  SQLQuery1.SQL.Text := 'INSERT INTO tblDictonary (Wort) VALUES (:sWort)';
  SQLQuery1.Prepare;
  for i := 0 to sl.Count - 1 do
  begin
    SQLQuery1.ParamByName('sWort').AsString:= sl[i];
    SqlQuery1.ExecSQL;
    //SqlTransaction1.Commit;
     if i mod 1000 = 0 then
     begin
       SqlTransaction1.Commit;
       Form1.Caption := IntToStr(i);
     end;
  end;
  SQLQuery1.Close;
 
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).

Dragon
Beiträge: 162
Registriert: Mi 31. Jul 2013, 15:07
OS, Lazarus, FPC: Ubuntu 16.04, CodeTyphon 5.80

Re: RAM verbrauchsproblem Postgresql+ZEOS

Beitrag von Dragon »

af0815: danke

Benutzeravatar
af0815
Lazarusforum e. V.
Beiträge: 6198
Registriert: So 7. Jan 2007, 10:20
OS, Lazarus, FPC: FPC fixes Lazarus fixes per fpcupdeluxe (win,linux,raspi)
CPU-Target: 32Bit (64Bit)
Wohnort: Burgenland
Kontaktdaten:

Re: RAM verbrauchsproblem Postgresql+ZEOS

Beitrag von af0815 »

Die Stringlist wird auch nicht freigegeben

Code: Alles auswählen

 
  sl := TStringList.Create;
  try
    sl.Delimiter := ' ';
    sl.QuoteChar := #$0;
    sl.DelimitedText := Origin;
    SQLQuery1.Close;
    SQLQuery1.Params.Clear;
    SQLQuery1.SQL.Text := 'INSERT INTO tblDictonary (Wort) VALUES (:sWort)';
    SQLQuery1.Prepare;
    for i := 0 to sl.Count - 1 do
    begin
      SQLQuery1.ParamByName('sWort').AsString:= sl[i];
      SqlQuery1.ExecSQL;
      //SqlTransaction1.Commit;
       if i mod 1000 = 0 then
       begin
         SqlTransaction1.Commit;
         Form1.Caption := IntToStr(i);
       end;
    end;
  finally
    sl.Free;
  end;
 

und das ist IMHO auch sicherer

Code: Alles auswählen

function LoadFile(FilePath: string): string;
var
  fm: tfilestream;
  s: string;
begin
  fm := tfilestream.Create(FilePath, fmopenread);
  try
    setlength(s, fm.size);
    fm.Read(s[1], fm.size);
  finally
    fm.Free;
  end;
  Result := s;
  setlength(s, 0);
end;
 


Edit: Das sl.free hat nur bei der sqlite Variante gefehlt. Das mit den Parametern und dem Prepare kann drastische geschwindigkeits vorteile bringen, da der sog. Ausführungsplan nicht neu erstellt werden muß. Wenn du jedesmal das SQL-Statement angibst, so wird auch in den SQL-DB Komponenten das ganze Statement neu verarbeitet, die Strukturen verworfen und neu erstellt und dann dem Server die Änderungen wieder geschickt. Das dauert verdammt lange. AUsserdem öffnet es Tür und Tor für SQL-Injections. Parameter sind schneller, weil der Server weis das sich nur die Daten geändert haben, ausserdem werden SQL-Kommandosa in Parametern icht erkannt und 'nur' als Text bewertet (=Schutz vor Injections).

Andreas
Zuletzt geändert von af0815 am Sa 29. Okt 2016, 21:29, insgesamt 1-mal geändert.
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).

Antworten