Announcement

Collapse
No announcement yet.

Probleme mit Delete Befehl

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

  • Probleme mit Delete Befehl

    Hallo,
    ich habe 2 Interbase-Tabellen, eine ist die Work-,
    die andere die Archiv-Tabelle.
    Beide Tabellen haben die gleiche Struktur, Spaltengröße = 150.
    Tagsüber schreibe ich 120000 Produktions-Datensätze mittels Insert-Befehl in die Work-Tabelle.
    In der Nacht füge ich diese neuen Daten mittels Insert Into...
    in die Archiv-Tabelle ein und rufe anschließend ein Delete auf
    die Work-Tabelle auf, die Work-Tabelle müßte nun "leer" sein....
    Aber das wars dann, die Work-Tabelle ist kaputt...
    Neue Daten für den nächsten Tag können nicht eingefügt werden,
    geschweige denn,sich die aktuellen Daten anzeigen lassen.

    Zur Testzwecken habe ich mittels ISQL-Tool und Borland DB-
    Oberfläche auf eine gefüllte Work-Tabelle den Delete-Befehl ausgeführt. Anschließend ein Select-Befehl und beide Programme
    waren im Reich der Ewigkeit.
    Wo liegt der Fehler ?
    Wir setzen Delphi 4 und Interbase 5.6 ein.

    Danke.

    Gruß

    Ralf Eberhard

  • #2
    Hallo Ralf,
    ich denke, dass das masive Löschen Probleme bereitet.
    Ich kenne es, wenn ich nach einem Versuch mal eben wieder 300.000 Datensätze lösche.
    So richtig schnell wird die DB dann erst wieder nach einem Backup / Restore.
    So viel ich weiss, dümpelt sonst der freigewordene Platz in der Datenbank so vor sich hin und bremst das System.
    Weiterhin solltest du beachten, dass die Version 5.6 noch voller Bug's war. Ein Umstieg auf Firebird oder die aktuellste IB - Version kann schon das Problem lösen.
    Ist denn sichergestellt, dass die Transaktionen sauber abgeschlossen (Commit) sind und Sweep aktiviert ist?<BR>
    Gruß, Fran

    Comment


    • #3
      Hallo Frank,

      Danke für Deine Antwort.
      Die Transaktion starte ich im Delphi-Programm mit StartTransaction und bestätige
      mit Commit im Try--Except- Block.
      Über eine Log-Datei protokolliere ich diesen Abschnitt mit.
      Soweit alles o.K.
      Ich habe ja auch die Probleme, wenn ich eine volle Tabelle mit Delete im DB-Explorer entleeren will.
      Zu Deinen Tipps habe ich noch folgende Fragen:
      a) Backup/Restore:
      Ich wollte einen Batchfile schreiben (enthält Aufruf:
      gbak.exe -user sysdba -password masterkey -b ...).
      Diesen Batchfile lasse ich dann in der Nacht nach dem Delete
      vom Delphi-Programm aus ablaufen.
      Geht das so oder müssen dafür die Connection zum Interbase
      geschlossen sein ?
      b) Firebirds:
      Kann ich einfach in dem bestehenden System die Interbase-Version 5.6 durch Firebirds ersetzen ?

      Gruß

      Ralf Eberhar

      Comment


      • #4
        Hi Ralf,
        ich sichere erst mal mit einer Kopie. Hierzu muss der Datenbank - Server heruntergefahren werden:
        <CODE>
        net.exe stop "Firebird Guardian - DefaultInstance"
        copy f:\ais\database\ais.fb h:\Archiv /y
        net.exe start "Firebird Guardian - DefaultInstance"
        </CODE>
        und nach dem Backup noch das Restore:
        <CODE>
        C:\Programme\Firebird\bin\gbak -r f:\ais\database\ais.fbk f:\ais\database\ais.fb -user SYSDBA -pas masterkey
        </CODE>
        Zumindest beim Restore müssen alle Connections geschlossen sein.
        Umstieg nach Firebird.
        Ich habe im Forum die Frage schon oft gelesen und bis jetzt den Eindruck, dass ein Umstieg sehr wohl möglich ist. Es gibt natürlich Fallstricke, da es Firebird mit der SQL - Syntax etwas genauer nimmt und manche Selects, die mal zulässig waren, mit einer Fehlermeldung quittiert. Da hilft nur ausprobieren. Wichtig ist:
        Die Datenbank über Backup (IB) und Restore (FB) auf das neue ODS zu portieren.
        Ach ja, die Benutzer musst du noch kopieren.
        Ich hab beim Umstieg nur die User aus der Benutzer DB exportiert und in die neue wieder eingelesen (mit IBExpert).
        Es sollte funktionieren.<BR>
        Gruß, Fran

        Comment


        • #5
          Hallo Ralf,<p>
          zeig mal das bisschen Code, wo dein Commit drinsteht. Oder hast du dich mit "commit steht im try except Block" verschrieben.
          <p>
          StartTransaction;
          try
          do bla ;
          finally
          Commit;
          end;
          <p>
          So etwa steht es ja hoffentlich bei dir dirn.
          <p>
          Wenn nicht, machst du kein Commit, und die Transaktionsmaske wird immer größer.
          <p>
          FB1.5 klappt wunderbar als Ersatz für ib5.6.
          Nur bei Joins musst du aufpassen, dass du keine doppeldeutigen Feldnamen ohne vorangestelltem Tabellennamen benutzt. Existiert der Feldname in beiden Tabellen, MUSST du den Tabellennamen davorschreiben. Unter IB war das noch nicht nötig (was von IB falsch ist).<p>
          Um einen kompletten Test der Anwendung wirst du nicht drumrumkommen.
          <p>
          Heiko
          <p>
          PS: Wo fügst du eigentlich die Datensätze in die Arvchivtabellen ein ? mit insert into archivtab (select from worktab)

          Comment


          • #6
            Hallo zusammen,
            vielen Dank für euere Antworten.

            a)Portieren nach Firebirds:
            Als Benutzer nehme ich immer sysdba, andere Namen vergesse
            ich immer wieder und der Kunde auch, so daß wir dann beide
            ein Problem haben.
            b) Die Datensätze werden mittels StoredProcedure in die
            Archivtabelle eingefügt, erst insert into ArchivDaten (select From workdaten) und dann kommt der Delete befehl Delete from workdaten.
            Delphi-Code sieht so aus:
            Procedure TMainForm.CreateStoredProcArchiviereLeistungsdaten ;
            Begin
            With StoredProcArchiv Do
            Begin
            DataBaseName := DBDataBaseArchiv.DataBaseName;
            StoredProcName := 'ArchiviereLeistungsdaten';
            Params.Clear;
            With Params.CreateParam(ftInteger,'I_JobNr', ptInput) do
            AsInteger := 0;
            End;
            End;

            Procedure TMainForm.ArchiviereLeistungsdaten;
            Begin
            If DBDataBaseArchiv.InTransaction = False Then
            DBDataBaseArchiv.StartTransaction;
            Try
            With StoredProcArchiv Do
            Begin
            Params[0].Value := 0; // JobNr für späete Aufgaben
            ExecProc;
            DBDataBaseArchiv.Commit;
            End;
            Except
            DBDataBaseArchiv.RollBack;
            End;
            End;

            Frage: Gibt es noch eine Möglichkeit eine IB-DB zu "säubern"
            ohne die Connection zu lösen, aber automatisch ?

            Gruß

            Ralf Eberhar

            Comment


            • #7
              Hallo Ralf,
              ich denke, mit der Vorgehensweise wirst du nicht glücklich.
              Es gäbe 2 Ansätze:
              Wenn es immer 120.000 Datensätze oder etwa gleich viel sind, dann kannst du die Records (max mögliche Datensätze), also z.B. 200.000 erzeugen und statt zu löschen leeren (mit eine Procedure). Wenn du noch ein Feld als Kennzeichen mit Index (GELOESCHT) hinzufügst, kannst du über einen View z.B.
              Select * from Tabelle where geloescht = 'F' die aktuellen Datensätze anzeigen lassen. Beim Insert holst du dir einen Record mit GELOESCHT = 'T' und änderst GELÖSCHT in 'F'.
              Oder du hälst alles in einer Tabelle und erweiterst ebenfalls um ein Feld ARCHIVIERT (alle Indexe um dieses Feld erweitern).
              Dann kannst du mit 2 Views alle archivierten oder aktuellen anzeigen lassen.
              Bezüglich Performance kannst du es ja mal mit deiner Archivtabelle testen.
              Gruß, Fran

              Comment


              • #8
                Hallo Ralf,<p>
                Verwendest du auch be beiden Programmen EXACT den gleichen Connection String ?. Vor IB6 konnte man mit verschiedenen Strings die Datenbank crashen.<p>
                Was heisst eigentlich "Work-Tabelle kaputt" ?<br>
                Was kommt denn beim Insert für eine Fehlermeldung.<br>
                In der Regel geht die Datenbank als ganzes tot und nicht eine Tabelle.<p>
                Heik

                Comment


                • #9
                  Hallo zusammen,
                  @ Heiko:
                  Es handelt sich um ein Programm:
                  Tagsüber werden mit Insert neue Daten in Work-Tabelle
                  eingetragen. In der Nacht erfolgt dann das Umkopieren von Work
                  nach Archiv und das Delete auf Work-Tabelle.
                  (Für beide Arbeiten nehme ich die gleiche Database-Komponente).
                  Am nächsten Tag erfolgt wieder das Einfügen neuer Daten und dabei geht das Programm gemäß Task-Manager auf 100% und das wars dann.
                  Das komische ist, die Datenbank kann irgendwie nicht ganz tot sein, denn lasse ich ein select-Befehl auf die Archiv-Tabelle laufen,
                  so werden mir korrekt die neuen Daten angezeigt.
                  Aber mache ich irgentwas mit der Work-Tabelle (Select oder Insert) passiert gar nichts, es erscheint die SQL-Eieruhr und dauert, dauert...
                  Ich habe diese Tests mit dem Datenbank-Explorer und mit Isql
                  durchprobiert, gleiche Verhalten, auch schon auf verschiedenen Rechnern mit NT oder XP.
                  Ich habe daraufhin eine Archiv-Tabelle mit Dummy-Daten gefüllt
                  und im Datenbank Explorer ein Delete from aufgerufen, hat etwas gedauert und der DB-Explorer war wieder bei mir und anschließend einfach auf Registerlasche Daten gewechselt und
                  in der rechten oberen Fensterecke auf Aktualisieren geklickt und
                  dann kam wieder die SQL-Eieruhr.....

                  @Frank:
                  Warum bezeichest Du meinen Weg als nicht "glücklich" ?
                  Deinen Weg bin ich anfangs auch gegangen, nur beim Einfügen
                  neuer Daten muß ich erst mittels Select-Befehl prüfen wohin,
                  und dann mit Update-Befehl aktualisieren. Dauert doch länger als
                  einfach nur mit Insert einfugen und verschenke Speicherplatz.

                  Gruß

                  Ralf Eberhar

                  Comment


                  • #10
                    Hallo Ralf,
                    @ Warum bezeichest Du meinen Weg als nicht "glücklich" ?
                    Weil ich gleiche Erfahrung gemacht habe wie du. Nämlich, dass riesige gelöschte Bereiche in der DB eine erhebliche Performanceeinbuße zur Folge haben.
                    Du bist damit zum Backup mit anschließendem Restore gezwungen, da sonst eben genau dieses Verhalten eintritt.
                    Ich weiss nicht, wie es bei anderen SQL - Servern funktioniert.
                    Ich hab z.B. eine Tabelle mit Kostenstellenbuchungen (ca. 900.000 Recs). Mit einem Import füge ich ca. 200.000 Records hinzu.
                    Dann lösche ich die 200.000 Records wieder. Damit tritt bei mir der gleiche Effekt ein. Arbeite ich auf der Tebelle, scheint die Anwendung einzufrieren. Irgendwie rödelt der Server sich am gelöschten Bereich tot. So viel ich weiss, wird der freie Bereich auch nicht wieder verwendet, so dass sich das Verhalten nach mehreren solcher Aktionen nur noch schlechter wird.
                    Ich mache übrigens alle Importe mit Proceduren. Die Prüfung, wohin etc. erfolgt in der Procedure, wo dann auch die entsprechenden Selects drin stehen. Das ist erheblich schneller als mit Selects im Code.
                    Wie gesagt, du wirst bei deinem Weg um das Backup / Restore nicht herumkommen. Vielleicht wird es ja mit FireBird 2 anders
                    Fran

                    Comment


                    • #11
                      Hallo Frank,
                      wenn ich Dich richtig verstanden habe,
                      legst Du in der Tabelle Kostenstellenbuchungen zuerst
                      900000 Dummy-Datensätze an und im Import
                      wird erst mit select kontrolliert wohin und dann mit
                      Update geändert.
                      Wie lange dauert der Vorgang bei Import 200000 Datensätze ?

                      Du muß bedenken mein Programm bekommt alle 1 bis 2 Sekunden von der Maschinensteuerung den Impuls
                      "Füge neue Produktionsdaten ein" (Import in Worktabelle),
                      ist das nicht zu eng bei Deinem Verfahren ?

                      Ich denke auch an Fall, daß der Kunde mal den Rechner über
                      Nacht ausschaltet und dann müßten in der nächsten Nacht schon Daten von 2 Tagen archiviert werden.

                      Gruß

                      Ralf Eberhar

                      Comment


                      • #12
                        Hallo,

                        du scheinst die Tabelle ja nach jeder Überführung ins Archiv komplett zu leeren. Sollte es da nicht geschickter sein die Tabelle komplett zu droppen und neu anzulegen(da du die Daten einfach verschiebst liegen da ja wohl keine Foreign Keys drauf))? Damit erspart man der Datenbank das Ganze unnötige Updaten von Indizes und das Schreiben ins Transaktionsprotokoll. Sollte deutlich schneller gehen und sollte einen sauberen Zustand hinterlassen.

                        Gruß
                        Ral

                        Comment


                        • #13
                          Hi Ralf,
                          ich lege keine Dummy - Datensätze an. Es sind Kostenbuchungssätze aus der FIBU in der Tabelle für spezielle Statistiken.
                          Einmal im Monat wird importiert. Dabei kommen jetzt ca. 200.000 Datensätze pro Import dazu.
                          Ich habe aber manchmal für Tests den letzten Import wieder gelöscht.
                          Danach hatte ich den von dir beschriebenen Zustand.
                          Der Import dauert ca. 10 min.
                          Dabei durchlaufe ich den Select aus der Fibu (Oracle) und füttere meine Procedure mit Daten und führe sie aus.
                          Bei der Procedure habe ich darauf geachtet, dass alle Selects sauber mit Indexen arbeiten. Dank IBExpert ist das ja möglich.
                          Die Proceduren sind meist sehr komplex und tragen Daten in mehrere Tabellen ein bzw. Updaten in verschiedenen Tabellen. Und bei komplexen Operationen sind sie die schnellste Alternative!
                          Du benötigst auch nur ein Prepare für die Procedure.

                          Gruß, Fran

                          Comment


                          • #14
                            Hallo,

                            du scheinst die Tabelle ja nach jeder Überführung ins Archiv komplett zu leeren. Sollte es da nicht geschickter sein die Tabelle komplett zu droppen und neu anzulegen(da du die Daten einfach verschiebst liegen da ja wohl keine Foreign Keys drauf))? Damit erspart man der Datenbank das Ganze unnötige Updaten von Indizes und das Schreiben ins Transaktionsprotokoll. Sollte deutlich schneller gehen und sollte einen sauberen Zustand hinterlassen.

                            Gruß
                            Ral

                            Comment


                            • #15
                              Hallo Frank,
                              ich denke gerade an die resultierende Datenmenge in der
                              Archiv-Tabelle nach. Ich habe pro Tag ca. 120000 Datensätze in
                              der Work-Tabelle, die Archiv-Tabelle soll die Daten ein Jahr halten. Das ja eine ganze Menge.
                              Schafft das der Interbase-Server überhaupt, auch im Hinblick
                              auf eine spätere Auswertung ?

                              Nachdem Jahr muß dann ja wieder die Archiv-Tabelle
                              mit Delete geleert werden

                              Gibt es für Interbase eine maximal obere Grenze an Anzahl
                              Datensätze ?

                              Gruß

                              Ralf Eberhar

                              Comment

                              Working...
                              X