Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Datenbanken (https://www.delphipraxis.net/15-datenbanken/)
-   -   Delphi Insert geschwindigkeit verbessern (https://www.delphipraxis.net/40048-insert-geschwindigkeit-verbessern.html)

Grumble 10. Feb 2005 12:27

Datenbank: Firebird • Version: 1.5.1 • Zugriff über: Sql (Zeos)

Insert geschwindigkeit verbessern
 
hallo leute,

ich moechte mich mal an die profis hier wenden und frag ob und wie ich das schreiben in die db schneller machen kann, dazu hier erstmal der quellcode:

Delphi-Quellcode:
if DM.ZCONDATA.Connected=false then DM.ZCONDATA.Connect;
        // schreiben der asset_data

      DM.ZQ.SQL.Clear;
      dm.ZQ.SQL.Add('INSERT INTO ASSET_DATA');
      dm.ZQ.SQL.Add('(ASSET_ID');          //a
      dm.ZQ.SQL.Add(',GEO_ID');            //b
      dm.ZQ.SQL.Add(',DATA)');            //c
      dm.ZQ.SQL.Add('values');
      dm.ZQ.SQL.Add('(:a,:b,:c);');
      dm.ZQ.ParamByName('a').AsInteger:=caid;
      dm.ZQ.ParamByName('b').AsInteger:=0; }
  lasset:=Tstringlist.Create;
  AssignFile(tempfile,OpeniDLG.FileName);
  Reset(tempFile);

  While not EOF(tempFile) do
  begin
    c:=c+1;
    ReadLN(tempFile,tempString);
    if c=1 then
    begin
    if (firstline) then
    begin
      dm.ZQ.ParamByName('c').AsString:=tempstring;
      dm.ZQ.ExecSQL;
    end;
    end
    else if c>1 then
    begin
      dm.ZQ.ParamByName('c').AsString:=tempstring;
      dm.ZQ.ExecSQL;
    end;
    bkrehab_fprogress.pb_progress.Position:=filepos(tempfile);
    bkrehab_fprogress.Panel2.Repaint;
    lasset.Append(tempstring)
  end;
dm.ZQ.SQL.Clear;
  dm.zq.SQL.add('commit retain;');
  dm.ZQ.ExecSQL;
in der while schleife lege ich den parameter c immer neu fest und schreibe per execsql in die db, nach schleifendurchlauf dann commit...
nun dauert das ganze bei ca. 6500 datensaetzen doch recht lange... ich hab mal was gelesen dass stored procedures schneller sind ... aber wie macht man sowas, geht das mit zeos... ist es ratsam? ich habe ja keine erfahrung damit... oder gibts andere moeglichkeiten die geschwindigkeit zu verbessern?

Stevie 10. Feb 2005 12:42

Re: Insert geschwindigkeit verbessern
 
Es gibt noch andere Möglichkeiten, das zu regeln.
Ich weiß nur nicht, welche am schnellsten ist, aber ich erwähn sie mal:
- Query auf CachedUpdates stellen, Sätze einfügen und anschließend mit ApplyUpdates übertragen
- In der Schleife ein Script aufbauen und das mit der TZSQLProcessor ausführen

PRehders 10. Feb 2005 12:47

Re: Insert geschwindigkeit verbessern
 
Hallo,

wenn die Table mehrere Indizes hat, kommt noch ein weiterer Weg in Frage.

Es ist nämlich auch die Frage, in welchem Rahmen dieser Masseninsert stattfindet: Wenn es sich um einmalige Aktionen handelt, oder solche, die nur zu definierten Zeitpunkten ohne andere Aktivitäten stattfinden, solltest Du dir überlegen:

- Indizes auf die Table löschen
- Inserts durchführen
- Indizes wieder einrichten

das geht normalerweise sehr viel schneller, weil die DB das anders organisieren kann als einen Masseninsert in schon bestehende Index-Dateien.

Bis dann

Peter

shmia 10. Feb 2005 12:56

Re: Insert geschwindigkeit verbessern
 
Du könntest viele (~500) INSERT - Anweisungen in einer Stringliste zwischen speichern
und dann in einem Rutsch ausführen.
Diese würde den Netzwerkverwerk deutlich reduzieren, da statt vieler kleiner Pakete
nur wenige grosse Pakete gesendet würden.

Dies geht aber nur, wenn die Datenbank, die Treiber und die Zeos-Komponenten diese mehrfachen
Befehle unterstützen (MS SQL Server + ADO kann das).
Mach einfach einen Test:
Delphi-Quellcode:
   // Beispiel für 2 Insert auf einmal
   // SQL Anweisungen mit ; getrennt
   DM.ZQ.SQL.Clear;
   dm.ZQ.SQL.Add('INSERT INTO ASSET_DATA Values(20, 30, 'Test1);');
   dm.ZQ.SQL.Add('INSERT INTO ASSET_DATA Values(20, 60, 'Test2);');
   dm.ZQ.ExecSQL;
Auserdem:
Delphi-Quellcode:
var
   qry : TQuery;
begin
   qry := dm.ZQ;
   // jetzt wird nur noch mit "qry" gearbeitet; dies spart etwas Rechenzeit
   qry.SQL.Clear;
   qry.SQL.Add('INSERT INTO ASSET_DATA');
   ...

Grumble 10. Feb 2005 12:58

Re: Insert geschwindigkeit verbessern
 
also netzwerkbelastung habe ich nicht, da die db lokal ist

ich probier nochmal rum, danke

VizeTE 11. Feb 2005 09:17

Re: Insert geschwindigkeit verbessern
 
mal noch ein Gedanke in eine ganz andere Richtung...falls der Inhalt deines "ZQ"-Querys mit Hilfe von Komponenten wie "DBGrids" oder ähnlichen angezeigt wird dann vor der Schleife
Delphi-Quellcode:
ZQ.DisableControls
und danach
Delphi-Quellcode:
ZQ.EnableControls
aufrufen. Wahrscheinlich hast du ja selbts daran gedacht aber man weiß ja nie ;)

Robert_G 11. Feb 2005 09:25

Re: Insert geschwindigkeit verbessern
 
Firebird kann kein Bulk DML, d.h.: Es wird IMMER auf einzelne Statements hinauslaufen.
Du einzig mögliche Optimierung, die ich erkennen kann wäre shmias Vorschlag mit dem Script. Oder zusätzliche eine SP, die das Statement nochmal verkleinert. :gruebel:
Aber das sind nur kleine Friemeleien, viel ändern wird sich da nix.

hmm... Hast du in der Tabelle Indizes auf String-felder? Benutzt du die auch? Wenn nicht: schmeiß die weg, das dürfte DML auf die Tabelle massiv beschleunigen. ;)
Die Idee mit dem Entfernen und Neuanlegen von Indizes will ich überhört haben. ;) Solche Friemeleien bekommst du niemals ( :!: ) validiert, und eine nicht validierbare DB ist eine sinnlose DB.

Grumble 11. Feb 2005 09:32

Re: Insert geschwindigkeit verbessern
 
also die tabelle die das ganze 'bremst' ist folgendermassen aufgebaut:

NAME TYPE

ASSETDATA_ID INTEGER PK
ASSET_ID INTEGER FK
GEO_ID INTEGER
DATA VARCHAR(32000)

meinst du ich soll das primary key feld raushaun?

Robert_G 11. Feb 2005 09:36

Re: Insert geschwindigkeit verbessern
 
Zitat:

Zitat von Grumble
meinst du ich soll das primary key feld raushaun?

uff :shock: Bloss nicht!
Ich meinte ungenutzte string-indizes! (welche es bei dir anscheinend nicht gibt)
Du solltest dir aber vielleicht überlegen, ob ein fortlaufender Index besser als PK passt. Dabei ist es für den kleinen Firebird auch nicht so schwierig die Eindeutigkeit zu prüfen.
Und du musst in Abfragen nur auf ein Feld verweisen, nicht auf 2. ;)

Und 32.000 Zeichen in einem Feld? :shock:
Ich weiß nicht wie gut FB BLOBs hndhabt, aber ich würde darauf wetten, dass ein BLOB schneller ist. ;)

Grumble 11. Feb 2005 10:10

Re: Insert geschwindigkeit verbessern
 
also die groesse von varchar scheint auch nicht die rolle zu spielen...
habs mal mit varchar(400) getestet... lief aufs selbe raus


Alle Zeitangaben in WEZ +1. Es ist jetzt 22:58 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz