Announcement

Collapse
No announcement yet.

ADO braucht ewig bei Schreiben in Access Datenbank

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • #16
    Moin Jochen...

    Ich traue Dir das parsen von Textdateien durchaus zu,allerdings
    woher willst du wissen,was geparst werden soll/muß ??

    Ich habe jetzt eine vorgeparste Textdatei angelegt,welche
    die Daten enthält.
    Das Prinzip ist sehr einfach gehalten,es sind pro Datensatz 12
    Zeilen,danach beginnt der neue Datensatz.
    Die Datenbank habe ich geleert und auch dem Projekt beigefügt.

    Das projekt enthält alle benötigten Dateien,eine vorkompilierte
    EXE und eine Informationsdatei wo ich ein klein wenig was
    reingeschrieben hab. (Benchmarkzeiten bei mir usw.)

    In der EXE sind 2 Buttons.
    Mit dem einen wird die Textdatei in das Stringgrid gelesen (und angezeigt) mit dem anderen Button werden die Daten in die Datenbank geschrieben.
    Ich habe es erst mal so gemacht,das es läuft
    In der Datenbank Schreibroutine gibt es bis auf "BatchOptimistic"
    keine weiteren Optimierungen.
    Ein "GetTickCount" Timer zur Zeitmessung ist integriert.

    Wer also Lust hat sich daran zu versuchen...
    ... viel Spaß und Erfolg damit

    Die 1.8 MB große ZIP-Datei findet ihr unter

    http://home.arcor.de/deuteros/d7-dbwrite.zip

    In diesem Sinne...

    Danke schon einmal im vorraus für eure Mühe.

    Cya de Helg

    Comment


    • #17
      Ist ja so ruhig hier :

      Comment


      • #18
        Hallo Helge,

        hab es mir herunter geladen, bin aber noch nicht dazu gekommen etwas zu machen. Viele Überstunden und zusätzlich noch 'in der Ausbildung' zum Admin in unserer GTR Liga. (und auch noch eine Freundin...) Vor dem Wochenende wird das bei mir nichts.

        Sorry Joche

        Comment


        • #19
          Moin Jochen...

          Kein Problem,jeder so wie er Zeit hat.
          Es hat mich nur stutzig gemacht,das sich hier nun garnichts
          mehr geregt hat,obwohl ich extra das Projekt angelegt habe,
          damit andere beim testen/optimieren möglichst wenig Arbeit haben.

          Muß ich wohl mit Leben - ich kann und will ja auch niemanden dazu
          zwingen sich mit meinen Problemen zu beschäftigen Es gibt
          mit sicherheit wichtigeres auf dieser Welt.

          In diesem Sinne...

          ... wenn sich jemand meldet,ist es schön , wenn nicht dann reiß
          ich auch niemanden den Kopf ab

          Cya de Helg

          Comment


          • #20
            aus einem Kleinwagen (Access) kann man selbst durch Tuning nur eine begerenzte Steigerung rausholen
            mein PC XP 2400, 512 MB RAM
            volle Datenbank (einmal schon eingelesen)
            originale Einstellung: 20 min Arbeitsspeicher und viertueller Speicher: am Schluss rund 200MB
            -
            meine Änderung: arbeiten mit Parameter, cursoerlocation auf clserver (auch bei connection), locktyp of ltoptimistic
            -
            adoquery1.SQL.Text:='SELECT * FROM pl_zo where pl_nr =:PL_nr and pl_zo_nr =l_zo_nr';
            //adoquery1.Open; Query zu lassen
            // if locate raus, Parameter Zuweisung rein
            //if Locate('pl_nr;pl_zo_nr',VarArrayOf([strtoint(stringgrid1.Cells[0,x]),strtoint(stringgrid1.Cells[2,x]) ]),[])=false
            close;
            Parameters[0].Value := strtoint(stringgrid1.Cells[0,x]);
            Parameters[1].Value := strtoint(stringgrid1.Cells[2,x]);
            open;

            if RecordCount = 0 then append else edit;
            meine Zeit: 7:40 min, also ein drittel nur wie bei locate, Speicher rund 60 MB

            zu beobachten war, dass bei test mit nur 1000 Datensätzen das locate noch doppelt so schnell war, bei 2000 etwas besser als gleich schnell, bei 3000 etwas schlechter als gleich schnell. Die tendenz ist also: je mehr Datensätze um so schneller ist es mit Parameter zu arbeiten
            Gruß Andrea

            Comment


            • #21
              Moin Andreas...

              Sorry,das ich mich erst jetzt melde,habe das WE aber für einen Angelscheinlehrgang genutzt...

              Danke erst einmal dafür,das du Dir die Zeit zum testen genommen hast. Ich werde deine Vorschläge einmal in meine Anwendung übernehmen und dann den Zeitunterschied messen.

              Das Access nicht unbedingt die schnellste DB ist,habe ich schon des
              öfteren gehört. Was mich aber eben stutzig macht:

              Die "originale" Anwendung,welche normalerweise diese Datenbank nutzt bekommt diese Daten+noch andere Datenbereiche (Planetenkopf,planetenzonen usw. welches ja auch nochmal mehrere 1000 Datensätze sind) in ca. 2 bis 2,5 Minuten geparst und in die DB geschrieben. Da sind (trotz optimierung) 7 Minuten nur für den Schiffsteil irgendwie noch 4-5 Minuten länger,als die andere Anwendung für die gesamte Datenbank benötigt.
              Das stimmt mich recht nachdenklich,da es ja anscheinend doch schneller gehen muß

              Die "originale" Anwendung für diese DB ist in VB geschrieben und
              soweit der Autor dieses Programms mir mal gesagt hat,hat er in
              VB wohl die DAO Schnittstelle (also den Vorgänger von ADO) genutzt.
              Ich habe weder von VB noch von DAO einen schimmer...
              Zumindest zeigt es aber auf,das die Datenbank durchaus in der
              lage ist,schneller zu arbeiten - fragt sich nur wie

              Cya de Helg

              Comment


              • #22
                Hallo,ich bins nochmal...

                @Andreas:
                Ich habe deine Modifikationen einmal umgesetzt und muß schon
                sagen,das es im gegensatz zu vorher durchaus um den Faktor 3 schneller ist.
                In ca. 1:55 Minuten war die Sache in die Datenbank reingeschrieben.

                Ich habe dann einmal für EDIT und APPEND jeweils 2 Routinen gemacht,und im EDIT Teil generell nur die Datenbankfelder modifiziert,welche sich ändern können (Planeten Nummer und Zonennummer können sich nicht mehr ändern,genauso wie die Dimension). Desweiteren habe ich in eben diesen EDIT Teil auch
                das FINDFIELD durch FIELDS[x] ersetzt.
                Ich hatte mir dadurch eigentlich noch einen gewissen Geschwindigkeitszuwachs erhofft,der tendiert aber gegen null

                Weil ich oben geschrieben habe,das die "original" Anwendung der
                Datenbank die Daten in 2-3 Minuten in die DB schaufelt,habe ich es
                nochmal nachgemessen.
                Mein Gefühl hatte mich getäuscht - die "originale" Anwendung schaufelt die Daten (Parsen+in DB schreiben) in ca. 44 Sekunden
                komplett in die Datenbank.

                Also irgendwie muß da noch was gehen

                Cya de Helg

                Comment


                • #23
                  eine weitere Verbesserung bringt:
                  - sql-Anweisung fest in Query reinschreiben
                  - im Objektinspektor unter Params bei den beiden params einstellen, dass diese integer sind
                  - vor dem Beginn (so hinter der Zeile "gettickcount) ein ADOQuery1.Prepared := true;
                  einfügen (das bringt den größten Gewinn, kann sicher auch schon im Objektinspektor erfolgen)
                  am Schluß passen dazu
                  ADOQuery1.Prepared := false;

                  -als Cursortyp=ctopenforwardonly
                  - kein Benuzten des Stringgrid, speichern in variablen, nach u=12 wird sofort in datenbank gespeichert (Arbeitsspeicherverbrauch nochmal halbiert, Geschwindigkeit ca 5%)
                  Das zusammen war zum Teil noch dreimal schneller als die letzten Änderungen.

                  Weitere Verbesserungen: VB verwenden, das kann wahrscheinlich besser mit Access umgehen. MS-Produkte verstehen sich nun mal besser untereinander.

                  Gruß Andrea

                  Comment


                  • #24
                    Ich habs noch schneller hinbekommen. Jetzt nutze ich eine Mischung aus parametisierter Abfrage und locate. Mein Quelltext sieht jetzt so aus.

                    procedure TForm1.Button3Click(Sender: TObject);
                    var zeit: Cardinal;
                    t,u: integer;
                    dummy: String;
                    f: Textfile;
                    param0, param1, param2, param3, param4,
                    param5, param6, param7, param8, param9,
                    param10, param11 : string;
                    nOldPlanet : integer;
                    begin
                    adoconnection1.Connected:=false;
                    adoconnection1.ConnectionString:='Provider=Microso ft.Jet.OLEDB.4.0;Data Source='+extractFilepath(paramstr(0))+'test.mdb;Mo de=ReadWrite;Persist Security Info=False';
                    adoconnection1.Connected:=true;

                    ShowMessage('Bei beendigung des Schreibvorgangs kommt eine Hinweismeldung!');

                    adoquery1.Close;
                    adoquery1.DisableControls;
                    // geändert
                    adoquery1.SQL.Text:='SELECT * FROM pl_zo where pl_nr =:PL_nr';
                    ADOQuery1.Prepared := true;
                    // neu
                    nOldPlanet := 0;

                    Zeit:=GetTickCount; //Ab hier die Zeit zum schreiben stoppen

                    Stringgrid1.Cells[0,0]:='Planet';
                    Stringgrid1.Cells[1,0]:='Dimension';
                    Stringgrid1.Cells[2,0]:='Zone';
                    Stringgrid1.Cells[3,0]:='Name Zone';
                    Stringgrid1.Cells[4,0]:='Besitzer';
                    Stringgrid1.Cells[5,0]:='Größe';
                    Stringgrid1.Cells[6,0]:='Beschreibung';
                    Stringgrid1.Cells[7,0]:='Temperatur';
                    Stringgrid1.Cells[8,0]:='Niederschlag';
                    Stringgrid1.Cells[9,0]:='Inhalt';
                    Stringgrid1.Cells[10,0]:='Zeit';
                    Stringgrid1.Cells[11,0]:='Tech';
                    Stringgrid1.Cells[12,0]:='Reserve';

                    assignfile(f,extractFilepath(paramstr(0))+'inhalt. txt'); //Textdatei mit Daten
                    reset(f);
                    t:=1; //Counter für Stringgrid1.row

                    while not eof(f) do
                    begin
                    for u:=0 to 12 do
                    begin
                    readln(f,dummy);

                    case u of
                    0 : param0 := dummy;
                    1 : param1 := dummy;
                    2 : param2 := dummy;
                    3 : param3 := dummy;
                    4 : param4 := dummy;
                    5 : param5 := dummy;
                    6 : param6 := dummy;
                    7 : param7 := dummy;
                    8 : param8 := dummy;
                    9 : param9 := dummy;
                    10 : param10 := dummy;
                    11 : param11 := dummy;
                    end;
                    end;

                    if param0 <> ''
                    then begin
                    with adoquery1 do
                    try
                    label2.Caption:='Schreibe Eintrag: '+inttostr(t);
                    application.ProcessMessages;

                    if nOldPlanet <> strtoint(param0)
                    then begin
                    nOldPlanet := strtoint(param0);
                    close;
                    Parameters[0].Value := strtoint(param0);
                    //Parameters[1].Value := strtoint(param2);
                    open;
                    end;

                    // geändert
                    //if RecordCount = 0
                    if locate('pl_zo_nr', strtoint(param2), []) = false
                    then Append
                    else Edit; //Prüfung ob Datensatz schon vorhanden (Anhand Planet Nr UND ZonenNummer)

                    if param0 <> '' then ADOquery1pl_nr.AsInteger:= strtoint(param0) else ADOquery1pl_nr.AsInteger:=-1; //Nummer Planet
                    if param1 <> '' then ADOquery1pl_dimension.Text:=param1 else ADOquery1pl_dimension.text:=' ';
                    if param2 <> '' then ADOquery1pl_zo_nr.asinteger:=strtoint(param2) else ADOquery1pl_zo_nr.asinteger:=-1;
                    if param3 <> '' then ADOquery1pl_zo_namen.text:=param3 else ADOquery1pl_zo_namen.text:=' ';
                    if param4 <> '' then ADOquery1pl_zo_besitzer.text:=param4 else ADOquery1pl_zo_besitzer.text:=' ';
                    if param5 <> '' then ADOquery1pl_zo_fus.asinteger:=strtoint(param5) else ADOquery1pl_zo_fus.asinteger:=-1;
                    if param6 <> '' then ADOquery1pl_zo_beschreibung.asstring:=param6 else ADOquery1pl_zo_beschreibung.asstring:='';
                    if param7 <>'' then ADOquery1pl_zo_temp.asstring:=param7 else ADOquery1pl_zo_temp.asstring:='';
                    if param8<>'' then ADOquery1pl_zo_nied.asstring:=param8 else ADOquery1pl_zo_nied.asstring:='';
                    if param9<>'' then ADOquery1pl_zo_ivo.asstring:=param9 else ADOquery1pl_zo_ivo.asstring:='';
                    if param10<>'' then ADOquery1pl_zeit.asinteger:=strtoint(param10) else ADOquery1pl_zeit.asinteger:=-1;
                    if param11<>'' then ADOquery1pl_tech.asinteger:=strtoint(param11) else ADOquery1pl_tech.asinteger:=-1;

                    post;
                    except
                    showmessage('Problem bei schreiben der pl_zonen' + #10#13 +
                    exception(ExceptObject).Message);
                    end;
                    inc(t);
                    end;

                    end;

                    //stringgrid1.RowCount:=t;
                    label1.Caption:='Einträge: '+inttostr(t-2); //Titelzeile und letzte Leerzeile werden abgezogen
                    closefile(f);

                    label3.Caption:='Zeit zum schreiben in die MDB: '+inttostr(GetTickCount-zeit)+' Millisekunden';
                    adoquery1.Close;
                    ADOQuery1.Prepared := false;

                    adoconnection1.Connected:=false;
                    showmessage('Das schreiben in die Datenbank ist beendet ');
                    end;

                    Jetzt läuft das schon recht zügig. Hätte eigentlich schon darauf kommen müssen, als ich festgestellt hatte, dass ein locate bei kleiner Datenmenge schneller ist als ein select auf einen Datensatz (und ein select auf 12 Datensätze ist auch nicht viel langsamer als auf einen Datensatz).

                    Gruß Andrea

                    Comment


                    • #25
                      Hallo zusammen,

                      ich versteh das Problem nicht wirklich; es werden Texte geparst und in ein Stringgrid geschrieben.
                      Anschließend wird das StringGrid zeilenweise durchlaufen und die eine oder andere Tabelle wertabhängig aktualisiert ?

                      Access ist SQL-optimiert, d.h. ich würde niemals zeilenorientiert arbeiten !

                      Ich würde hier eine Klasse (statt StringGrid) anlegen und eine TList für die Aufnahme der einzelnen Einträge.
                      Nach dem Füllen der Klasse erstelle ich im Zielfolder eine SCHEMA.INI und exportiere die TList im csv-Format in das gleiche Verzeichnis.
                      Dann importiere ich die exportierte csv in die Datenbank (temporär) und update anschliessend meine Basistabellen.

                      Ist sicherlich mehr Arbeit, aber der (zeitliche) Erfolg gibt Recht

                      mfg Holger Rogg

                      Comment


                      • #26
                        Moin

                        @Holger:
                        Ich bin nicht so gut im Programmieren,schon garnicht mit
                        Datenbanken usw. Daher kann ich Deine Aussage weder bestätigen noch verneinen.
                        Ich versuche dieses Projekt so durchzuführen,das ich es verstehe und es nicht unnötig viel Arbeit macht,denn ich möchte anderen damit einen gefallen tun,ich persönlich habe von den ganzen geparsten Daten eigentlich nichts mehr,weil ich bei dem zugehörigen Textbasiertem Spiel nicht mehr mitspiele.
                        Und weil es ein gefallen für andere ist,hatte ich ehrlich gesagt auch
                        keine Lust mich jetzt noch mit CSV (wovon ich garkeine Ahnung habe). Da ich später das Tool hier und da nochmal an die aktuellen gegebenheiten anpassen muß,wollte ich es in für mich bekannten Stil lassen - ob er perfekt ist sei jetzt einmal dahingestellt,grins...

                        Sprich: Das Tool ist bis auf die Optimierungen sogesehen fertig,
                        daher möchte ich das schon vorhandene Rad nicht unbedingt neu erfinden,ich hoffe du bist mir deshalb nicht böse

                        @Andreas:
                        Sorry,das es ein paar Tage gedauert hat,aber ich mache hier gerade meinen Fischereischein udn sitze deswegen nicht so oft
                        am Computer

                        Ein paar von deinen 2. Optimierungspost habe ich umgesetzt,allerdings hatte ich nicht die Effekte,wie sie bei Dir anscheinend aufgetreten sind.

                        Mit SQL Anweisung fest in Query schreiben,konnte ich leider nicht so recht was anfangen

                        Unter dem Objectinspector hatte ich für PARAMS noch garnichts stehen,habe dann 2 neue Felder dort angelegt und so benannt,wie du sie in der SQL Anweisung genannt hast. Dort habe ich dann auch Integer eingestellt.
                        Ob diese beiden Einstellungen aber überhaupt im Programm "berücksichtigt" wurden,weiß ich nicht,denn der Zeitgewinn war = 0. Ich habe aber noch nie mit dem PARAMS von ADO gearbeitet,vielleicht habe ich auch etwas falsch gemacht ?

                        Prepared war im Objectinspector schon auf TRUE gestellt.
                        Die umstellung von Cursortyp=ctopenforwardonly hat ca. 6-8 Sekunden gebracht.

                        Das Stringgrid habe ich noch nicht gestrichen,das fliegt erst raus,wenn das Tool komplett fertig ist - das dient mir noch zur
                        Kontrolle der geparsten Daten...
                        (Eure Version ist ja speziell nur zur optimierung erstellt worden)
                        -----------------------------------------------------------------
                        Deinen letzten Post habe ich noch nicht umgesetzt.

                        ADOquery1pl_nr.AsInteger

                        Wo legst du das fest,das die Adoquery die Felder "FEST" einträgt ?
                        Stelle mich anscheinend irgendwie etwas blöd an
                        Das würde mich noch interessieren, und wie das mit dem PARAMS im Objectinspector genau funktioniert,denn ich hatte dein PARAMS Code so implementiert OHNE das ich im Objectinspector was dahingehend eingestellt hatte. Habe mir da auch keine Gedanken gemacht,weil es offensichtlich funktionierte...

                        Cya de Helg

                        Comment


                        • #27
                          <Prepared war im Objectinspector schon auf TRUE gestellt.>

                          Dann konnte der Geschwindigkeitsgewinn nicht mehr kommen.

                          <Mit SQL Anweisung fest in Query schreiben,konnte ich leider nicht so recht was anfangen >

                          Im Objektinspektor Eigenschaft "SQL". Wenn da dann "SELECT * FROM pl_zo where pl_nr =:PL_nr" drinnen steht, erscheint unter params "PL_NR".

                          <Wo legst du das fest,das die Adoquery die Felder "FEST" einträgt ?>

                          Doppelklick auf TADOQuery oder Rechte Maustaste --> Feldereditor, dann rechte Maustaste --> alle Felder hinzufügen

                          <Die umstellung von Cursortyp=ctopenforwardonly>

                          Muss bei meiner letzten Optimierung, wo ich mit dem select "alle" Daten zur selben "PL_NR" hole wieder rückgängig gemacht werden, sonst hast du alle Daten doppelt drinnen. Dieser Cursortyp kann nur in eine Richtung.
                          Bei mir hat das Einlesen auf meinem Athlon 2400 nur noch 70 sek gedauert.

                          Gruß Andrea

                          Comment


                          • #28
                            Moin Andreas...

                            Danke für Deine Mühe,ich werde das mal versuchen umzusetzen.

                            Aber erstmal werde ich das schöne Wetter noch nutzen

                            Cya de Helg

                            Comment

                            Working...
                            X