Announcement

Collapse
No announcement yet.

TClientDataSet Geschwindigkeits-Problem

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

  • TClientDataSet Geschwindigkeits-Problem

    Hallo, Zusammen oder auch einzeln!

    2000 Datensätze, etwa 2,5 MB werden lokal bearbeitet. Aktenkoffer-Prinzip = werden vor Ort in einem File gespeichert und wieder geladen.

    Die Datensätze werden über eine TList mit einem Tree verbunden. Zur Identifizierung gibt es 'SID' = SelfID, 'PID' = ParentID.

    Soweit alles fein und rattenschnell - aber! Der User (Im Moment ich, der Esel) legt einen neuen Datensatz an (Append oder Insert ist egal), schiebt diesen im Tree an erste Stelle als ersten Root und hängt den bisherigen Root als FirstChild an FirstRoot. Alle Zeiger werden richtig geändert .(Auch noch prima).

    Wird der CDS nun gespeichert und dann wieder geladen, knallt der erste Datensatz als Child auf ein Parent, was noch nicht existiert, denn dieses (bzw. sein Datensatz) steht am Ende oder mittendrin in der Datei. Na schön, denk ich mir, dann speichern wir doch mal beim Save den AbsoluteIndex vom Tree mit (Was ja über die TList-Verbindung KEIN Problem ist) und schon dauert das Speichern 8 Sekunden für popelige 2000 Datensätze, weil die durchiteriert werden müssen.

    Nun stell ich mir mal vor, da sind 10000 Datensätze drin - Tests haben ergeben, dass das Problem exponentiell steigt - womit wir dann über 30000 Datensätze mal lieber nicht nachdenken.

    Irgendeine Ordnung muss her, die möglichst nur wenige Knoten betrifft, denn laden und indizieren geht rasant, aber alle durch-editieren und posten dauert ewig.

    Hat jemand eine Idee - kann auch eine ganz andere Lösung sein - etwas zeitnah wäre auch klasse.

    Danke, Bernhard

  • #2
    Hallo Bernhard,<p>
    An welcher Stelle entstehen denn die 8 Sekunden konkret? Kann es sein, dass Du mit einer TList arbeitest, in der alle Objekte Einträge der Reihe nach abgelegt sind? Und dann noch eine Frage: Ein Tree hat doch im Allgmeinen eine sehr effizient Verwaltung (zumindest der Virtual Tree von Mike Lischke), warum speicherst Du die Daten noch einmal in einer Liste parallel dazu?<p>
    Mal generell habe ich sehr angenemme Erfahrungen mit ObjectList-Ableitung gemacht. Also jeder Eintrag war ein Object, welches selbst mehrere Einträge von sich selbst aufnehmen kann, aber nicht muss. Iterationen dadurch waren immer Pfeilschnell, auch bei großen Datenmengen. Jedoch habe ich jetzt nicht darüber nachgedacht, wie sich das dann mit dem Verschieben von Knoten innerhalb der Listen verhält, vermutlich ist dann die TList geeignter, da man dort die Speicherverwaltung besser kontrolliern kann. <p>
    Ich weiß, bis jetzt sind dass nur Ideeen, für ein Gespräch... <p>
    Schöne Grüße, Mario Noac
    Schöne Grüße, Mario

    Comment


    • #3
      Hallo Mario

      ...warum speicherst Du die Daten noch einmal in einer Liste parallel dazu? ...

      Am TreeNode "hängen" Daten, zum Teil RTF-Texte etc. somit gilt:

      ...Kann es sein, dass Du mit einer TList arbeitest, in der alle Objekte Einträge der Reihe nach abgelegt sind?...

      Die TList verbindet den DataSet des TClientDataSet mit dem Treeview, sodass beim wechseln des Datensatzes der Knoten, bzw beim wechseln des Knotens der Datensatz gefunden wird.

      Der Knoten selbst ist nur eine "Überschrift" im Datenteil des DataSet.

      Meine letzte theoretische Lösung sieht vor, dann und nur dann, wenn das Problem auftritt - über ein locate den Datensatz zu suchen (über SID = PID ja kein Problem), den Cursor auf die Stelle des Problems zurückzuführen (Bookmark), dort ein Insert zu tätigen, die Daten umschreiben, den Datensatz an der alten Stelle löschen.

      Damit wäre das Problem behoben - mit der Brechstange. Wie lange DAS dauert, wie häufig das auftritt und ob im Endeffekt ein Gewinn dabei rauskommt, müßte ich erstmal testen.

      Alternativ müßte ich sonst auf pures XML übergehen, weil das zum Teil doch sehr schnell geht, gerade wenn man selbst in ein reines Textfile schreibt. Geht der Weg über ein DOM - was an sich vorzuziehen wäre, allein wegen zukünftiger Änderungen in XML - dann müßte auch hier wieder auf Geschwindigkeit getestet werden.

      Damit kommen wir zur letzten Frage:

      ... An welcher Stelle entstehen denn die 8 Sekunden konkret?...

      Das Tree zu durchlaufen (iterativ oder rekursiv) spielt keine Rolle, die Zeit bleibt beim Schreiben in den TClientDataSet. Am schnellsten ging noch das völlig Neu-Erstellen des TClientDataSet - aber auch das verhält sich von den Zeiten unter XP exponentiell, und ist erheblich langsamer als unter W2K! Das Teil (bzw Midas) scheint nur fürs LESEN von Borland optimiert zu sein.

      Wer immer eine Idee hat, mit welcher Technik man das Problem löst, ist herzlich willkommen, sich zu äußern. Die Bedingung ist aber, zumindest das Aktenkoffer beizuhalten - also alle Daten müssen per File local gebunkert und von dort auch wieder gelesen werden können.

      Erst mal Gruss zurück,
      Bernhar

      Comment


      • #4
        Hallo Bernhardt,

        ... Das Tree zu durchlaufen (iterativ oder rekursiv) spielt keine Rolle, die Zeit bleibt beim Schreiben in den TClientDataSet. <BR>
        Ist das wirklich so, mit einem zuverlässigen Profiler erhärtet? Ich hatte mal ein ähnliches Problem und am Ende war es doch das Durchlaufen der TreeView! Ein lineares Durchlaufen geht nämlich (mit der standard TreeView) gar nicht. Die Navigation über AbsoluteIndex läuft immer auf eine Rekursion hinaus, wenn man an einem Blatt ohne Unterknoten angekommen ist. Das von die beobachtete exponentielle Zeitverhalten deutet auch schon auf so was hin. <BR>
        Ich habe mir damals mit einem Array der Elternknoten für jede Verzweigungsebene (Level) geholfen, damit ich beim Zurückspringen (niedrigerer Level) den zugehörigen Knoten schnell wieder finden konnte. Danach war das Zeitverhalten linear.<BR>
        Insgesamt wären aber vielleicht die "Virtual treeViews" von Mike Lischke einen Versuch Wert. ( virtualtreeview.soft-gems.net ) Die sind auf Geschwindigkeit getrimmt und benutzen auch intern nicht die Windows-TreeView. <BR>
        PM

        Comment


        • #5
          Es spräche noch ein Punkt für den VirualTree. Er bietet die Möglichkeit, beliebige benutzerdefinierte Daten den Knoten zuzuordnen (Beispiele sind bei). Das käme natürlich einem "Neuentwurf" gleich.<p>
          Eine Idee wäre, den AbsoluteIndex zu verwerfen und den Tree als Stream in einer Datei abzulegen. Somit steht die Einleseproblematik nicht mehr und die Datensätze in der DB müssten nicht immer wieder angefasst werden, um neu durchzunummerieren.<P>
          Alternativ könntest Du bei Deiner jetzigen Logik alle Knoten, deren Parents noch nicht existieren, an einen WorkRoot legen und bei Anlegen des passenden Parents, die Knoten "rüberschieben". Iterativ wirft es zwar ein paar Probleme auf (Iteration auch im WorkRoot), aber für den Fall hier unter Umständen eine gute Lösung?<p>
          Mari
          Schöne Grüße, Mario

          Comment


          • #6
            Ich habe mir das VT angesehen, obwohl die von mir in diesem Zusammenhang genutzte Komponente von 9Rays auch verdammt schnell ist. Die Daten zu "streamen", wäre eine Möglichkeit. Muss ich mal drüber nachdenken. Die Nummer mit dem Workroot
            hatte ich auch schon in Erwägung gezogen. Also liegt die Lösung wahrscheinlich in der Zusammenfassung aller bisheriger Beiträge zu einer Lösung.

            Erstmal Danke, zumindest zeigen Eure Beiträge dass ich in die richtige Richtung denke.

            Gruss
            Bernhar

            Comment


            • #7
              Hallo Bernhard,

              Zwei Lösungswege:

              1)
              Speichere in Deiner Datei auch noch den Level eines Knotens. Beim Auslesen verwendest Du dann eine Sortiereung 'order by Level, SID, PID...' und schon kann es nicht mehr vorkommen, dass ein Datensatz auf einen noch nicht vorhandenen Parent trifft.

              Das erfordert natürlich erhöhten Aufwand (und erzeugt somit potenzielle Fehlerquellen) bei der Verwaltung der Knoten in der DB. Umhängen eines Knotens erfordert dann z.B. Änderungen aller Levelinformationen der Kindknoten.

              2)
              Verwende tatsächlich den affenartig schnellen VirtualTree von M. Lischke, Knalle alle Nodes, deren Eltern noch nicht geladen sind an den Rootknoten und hänge nach dem Laden solange Knoten iterativ um bis jeder Knoten tatsächlich seinen korrekten PID-Knoten hat.

              Gruß
              Gesine

              P.S.
              Der o.g. 'Lischke-Tree' erzeugt z.B. 100000 Knoten in Sekundenbruchteilen und wird das Laufzeitverhalten kaum beeinflussen. Ich verwende übrigens Lösung 2 und habe mit ca. 250000 Knoten keine Probleme.

              &#10

              Comment


              • #8
                Hi Gesine! (lange nix von dir gesehen, was natürlich an mir liegt)

                Das wollte ich ja, aber das Problem liegt in der Speicherzeit des CDS.

                Leg mal 10.000 Datensätze an und speicher den CDS. Das Speichern dauert 0.1 sec, das Anlegen eine Ewigkeit. Das gleiche Problem besteht bei Update - sonst .......

                Also worknode oder copy/insert ist schon der schnellere Weg.

                da du ja erwiesenermaßen sql-spezi bist: kennst du vielleicht einen cds-ersatz, der schneller ist?

                dennoch: Danke, gruss,bernhar

                Comment


                • #9
                  Hi Berhard,

                  uups, das ging ja schnell...
                  Was für eine Datenbank steht denn im Hintergrund?

                  P.S.
                  Lag nicht an Dir, sondern daran, dass ich längere Zeit mit Aufgaben beschäftigt war, bei der Delphi-Entwicklung eine untergeodnete Rolle spielt

                  Comment


                  • #10
                    Hi und wow ... das ging ja schnell ;-)

                    Im Augenblick steht das im Grunde im Hintergrund, aber "Homebase" ist Firebird

                    gruss
                    bernhar

                    Comment


                    • #11
                      Hi Bernhard,

                      Huch hier gibts ja einen neuen Knopf. Meine beiden Vorschäge wurden schon von Mario und Peter präsentiert.

                      Wenn Du ein cds ohne Backend betreibst, dann darfst Du Dich nicht über mieses Laufzeitverhalten wundern. Das Ding ist eher für Handtäschchen als für Koffer.

                      Dein jetziges Vorgehen hat den generellen Fehler, dass Dein Tree nicht getrennt von der Datenmenge ist. Jeder Knotenwechsel, -operation in selbigem führt zu einem von Dir kaum beeinflussbarem Move im Dataset. Trenne beides. Lies alle Knoten (also Caption, ID, PID) ein. Die Zusatzdaten eines Knotens, die Du wahrscheinlich rechts davon anzeigen möchtest, liest Du erst in dem Moment, wo auf dem Knoten positioniert wird. Dieses Grundprinzip perfektioniert der bereits viel zitierte 'Lischke-Tree' und macht ihn so sauschnell

                      Comment


                      • #12
                        Frau oder Mann, ich bin doch kein nut!

                        Das Problem ist nicht der Tree - ob lischke, 9rays oder schießmichtot (solange man nicht mit comctrl-basierten arbeitet) ist völlig egal.

                        warum wollen alle immer das problem da sehen, wo es nicht ist

                        Comment

                        Working...
                        X