Announcement

Collapse
No announcement yet.

Welches Verfahren ist besser?

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

  • Welches Verfahren ist besser?

    Hallo,

    ich habe eine größere Aktion, bei der drei Queries benötigt und diese in einer Schleife ca. 2000 mal ausgeführt werden, zunächst nach diesem Muster realisiert:
    <pre>
    q := TQuery.create(self);
    try
    q.sql.add(...
    q.open;
    ...
    finally
    q.free;
    end;
    <pre>
    Das Ganze wurde immer langsamer und nach Beendigung dauerte es ziemlich lange, bis sich das Fenster überhaupt schließen ließ.
    Im Task-Manager (W2K) unter Systemleistung fiel mir auf, dass sich die Zahl der Handles laufend reduzierte.

    Ich habe dann den Code geändert und eine Query im Formular erstellt, diese dann immer wieder geschlossen und geöffnet.
    Das ging dann alles um Faktor 6 schneller, auch beim Schließen keine Probleme.

    Ich dachte nun, das nach q.free die Sache doch sauber aus dem Speicher entfernt wird. Habe ich da was nicht berücksichtigt?

    Dankbar für Hilfe ist...

    Felix

  • #2
    Hallo,

    wenn in einer Schleife eine SQL-Anweisung gleich 2000-Mal abgeschickt werden soll, ist folgendes sinnvoll: <br>
    1. Eigene TQuery-Instanz im Objektinspektor konfigurieren und für die variablen Teile <b>Parameter</b> einsetzen <br>
    2. Vor dem Eintritt in die Schleife die TQuery-Methode <b>Prepare</b> aufrufen <br>
    3. In der Schleife die Parameter-Werte übergeben und die Abfrage nur ausführen, aber die Eigenschaft <b>SQL</b> niemals ändern! <br>
    4. Nach der Schleife die TQuery-Methode <b>UnPrepare</b> aufrufen

    P.S. Die TQuery-Methode Free kümmert sich nur um den Speicher, den die VCL für diese TQuery-Instanz angefordert hat. Wenn aber eine SQL-Anweisung zur Datenbank geschickt wird, werden auch dort Ressourcen belegt

    Comment


    • #3
      Hallo Herr Kosch,

      vielen Dank für die Hilfe.
      Habe ich es richtig verstanden, dass die Ressourcen, die durch die SQL-Anweisung in der Datenbank belegt werden, durch <b>UnPrepare</b> wieder freigegeben werden?

      Gruß Feli

      Comment


      • #4
        Hallo,

        ja - wenn man <b>vorher</b> in eigener Regie auch Prepare aufgerufen hat

        Comment


        • #5
          Alles klar, danke.

          Gruß Feli

          Comment


          • #6
            Wie sieht es aber mit ADO aus?

            <PRE>
            ...
            var
            FQryGetParents:TADOQuery;
            ...
            FQryGetParents:=TADOQuery.Create(NIL);
            with FQryGetParents do begin
            Connection:=FConnection;
            Prepared:=True;
            SQL.Text:=
            'SELECT RefParent FROM TblContainers WHERE Pkey=key and RefParent<>Pkey';
            end;
            ....
            var
            pkeyList:TStringList;
            ...
            for i:=0 to 100 do begin
            with FQryGetParents do begin
            Close; // must close the query here otherwise the parameter value will not be assigned
            Parameters[0].Value:=AContainerPkey; // set parameter value
            Open; // reopen the query -> is it still prepared and the same cursor
            if IsEmpty then
            break;
            AContainerPkey:=Fields[0].AsString;
            ResultList.Add(AContainerPkey);
            end; // with
            end; // for
            </PRE>

            Wird das Statement in diesem Code Fragment jetzt immer mit dem gleichen DB Cursor ausgeführt oder immer wieder neu selektiert?

            Wie kann ich dann eigentlich das tatsächlich ausgeführte Statement (d.h. Parameter ersetzt durch aktuellen Wert) rausbekommen

            Comment


            • #7
              Können Sie ja in Ihren Artikel in der nächsten Ausgabe des Entwicklers aufnehmen

              Comment


              • #8
                Hallo,

                &gt;Können Sie ja in Ihren Artikel in der nächsten Ausgabe des Entwicklers aufnehmen!

                zu spät - aber in meinem ADO-Buch gehe ich genauer auf Prepared ein. Weil die meisten Entwickler das Vorbereiten über Prepare "vergessen", hat Microsoft dieses Know-how fest in die eigene OLE DB-Provider eingebaut. Somit ist ADO effektiver, wenn der Entwickler die Eigenschaft Prepared <b>nicht</b> im eigenen Sourcecode aktiviert. Wenn das Programm über ADO auf eine Microsoft SQL Server 7/2000-Datenbank zugreift, läuft alles (auch ohne Prepared) über eine spezielle System-Stored Procedure, so dass jede parametisierte SQL-Anweisung optimal ausgeführt wird. Der zusätzliche Aufruf von Prepared verschlimmert die Situation, da jeweils ein unnötiger zusätzlicher Aufruf erfolgt.
                &#10

                Comment


                • #9
                  1.) Danke für diese sehr interessante Anwort - ich glaube die wenigstens wussten das.
                  2.) Ich werde das Buch kaufen.
                  3.) Da werde ich wohl mein Programm umschreiben müssen. Man merkt das übrigens. Selbst Statements die nicht Parameter enthalten werden beim zweiten mal viel schneller ausgeführt als beim ersten Aufruf. Der OLE DB Treiber oder der SQL Server verhalten sich also von sich aus recht clever.

                  Vielen Dan

                  Comment

                  Working...
                  X