AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Datenbanken TADOQuery.LoadFromFile sehr langsam
Thema durchsuchen
Ansicht
Themen-Optionen

TADOQuery.LoadFromFile sehr langsam

Ein Thema von Bbommel · begonnen am 20. Jun 2012 · letzter Beitrag vom 21. Jun 2012
Antwort Antwort
Bbommel

Registriert seit: 27. Jun 2007
Ort: Köln
655 Beiträge
 
Delphi 12 Athens
 
#1

TADOQuery.LoadFromFile sehr langsam

  Alt 20. Jun 2012, 17:32
Datenbank: MSSQL/Text • Version: 2008R2 • Zugriff über: ADO
Hallo zusammen,

bei einer TADOQuery ist es ja möglich, das Ergebnis aus einer Abfrage mit SaveToFile in eine Datei zu schreiben und mit LoadFromFile wieder aus dieser zu lesen. Nun wollte ich diese Funktion nutzen, um Kunden, bei denen Probleme auftreten, besser helfen zu können, indem diese mir schnell die relevanten Daten bereitstellen können (ohne gleich einen echten Datenbank-Backup machen zu müssen oder so), die ich dann bei mir importieren und falls nötig mit dem Debugger in aller Ruhe analysieren kann.

Soweit der Plan. Das Exportieren der Daten, also der Ergebnismenge einer Abfrage, klappt auch tadellos. Einfach "SaveToFile" von TADOQuery aufgerufen und noch nicht mal einer Sekunde ist auch eine größere Datenmenge auf die Platte geschrieben (zumindest jetzt gerade erst mal im lokalen Test).

Nun wollte ich die so entstandenen Dateien wieder einlesen und diese als Ergebnis der Abfrage benutzen, anstelle die wirklich auf einem Server auszuführen. Prinzipiell klappt genau das auch mit "LoadFromFile" problemlos: Die Daten werden geöffnet und ich kann sie im Programm verarbeiten, als kämen sie direkt vom Server. Toll!

Aaaaaber: das Ganze macht mir richtig Probleme, sobald viele Datensätze im Ergebnis sind. Dabei, so merke ich gerade, ist es völlig egal, ob ein einzelner Datensatz viele Felder und Infos hat, sondern nur die Anzahl der Datensätze scheint ihm das Genick zu brechen. Das Problem ist dann nämlich, dass die Verabeitung immer langsamer und langsamer wird.

So etwas ähnliches hatte ich früher schon einmal, damals nur beim direkten Zugriff auf den Server. Damals hat es geholfen, etwas an den Cursor-Einstellungen rumzuspielen. Habe ich gerade auch wieder versucht, aber bisher erfolglos.

Hat jemand eine Idee, wo man hier noch etwas schrauben kann? Wäre zu schade, wenn ich diese großartige Funktion nicht nutzen könnte...

Gespannt auf Tipps hoffend
Bommel
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.033 Beiträge
 
Delphi 12 Athens
 
#2

AW: TADOQuery.LoadFromFile sehr langsam

  Alt 20. Jun 2012, 17:46
Das ADOQuery kenn ich so nicht.
Nicht daß es zusätzlich noch die geladenen Felder irgendwie in die DB überträgt. (denk/hoff ich mal nicht)

Aber mit dem TClientDataSet, bzw. dem TdxMemData geht das Laden und Speichern eigentlich recht flott.


Hast du eventuell irgendwo irgendwelche Insert/Post/Scroll-Events, welche da reagieren könnten?
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests
  Mit Zitat antworten Zitat
Bbommel

Registriert seit: 27. Jun 2007
Ort: Köln
655 Beiträge
 
Delphi 12 Athens
 
#3

AW: TADOQuery.LoadFromFile sehr langsam

  Alt 20. Jun 2012, 18:02
Hm, wäre die Frage, ob ein ClientDataSet die Daten lesen könnte, die von einem ADOQuery (wobei die Funktion von TCustomADODataSet geerbt wird) geschrieben wurde...

Irgendwelche besonderen Events oder so habe ich eigentlich nicht definiert. Die ADOQuery wird zur Laufzeit erzeugt, bekommt beim normalen Import die passende Connection, Cursor und LockType zugewiesen und dann mache ich damit nichts anderes, als diverse Abfragen durchzurattern und die Daten bei mir in lokale Datenstrukturen im Speicher zu importieren.

Dass er versucht, auf die eigentliche Datenbank zuzugreifen, kann eigentlich nicht sein, weil ich die "Connection" in der Query auf nil setze, bevor ich das LoadFromFile aufrufe. Also kennt er die echte Datenbank dann noch nicht mal mehr.

So, "muss" jetzt in den Feierabend. Falls noch jemand Ideen hat, würde ich mich freuen. Nicht wundern, wenn ich selbst erst morgen wieder antworte.

Bis denn
Bommel
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.033 Beiträge
 
Delphi 12 Athens
 
#4

AW: TADOQuery.LoadFromFile sehr langsam

  Alt 20. Jun 2012, 19:30
Notfalls könnte man es vor dem Speichern ja noch schnell umkopieren.

Eventuell/Vermutlich gibt's das auch schon in D2009 ... Delphi-Referenz durchsuchenTDBXDataSetReader ... mit .Create rein und über .CopyReaderToClientDataSet wieder raus.

(Das Ding wird übrigens intern auch vom DataSnap verwendet, für die Übertragung der DataSets, bzw. DataSnap basiert auf dem ganzen DBX-Zeugs )
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests
  Mit Zitat antworten Zitat
Bbommel

Registriert seit: 27. Jun 2007
Ort: Köln
655 Beiträge
 
Delphi 12 Athens
 
#5

AW: TADOQuery.LoadFromFile sehr langsam

  Alt 21. Jun 2012, 12:05
Hier mal ein Update zum Stand der Dinge - mit ein paar neuen Erkenntnissen, auf deren Grundlage vielleicht ja noch jemand einen neuen Tipp hat.

Zunächst zu himitsu: Ja, TDBXDataSetReader gibt es auch schon in D2009 und müsste, da TADOQuery ein Nachfolger von TDataSet ist, auch damit funktionieren. Aber ehrlich gesagt ist mir noch nicht so richtig klar geworden, was ich dann damit machen soll und wie mir das helfen könnte.

Ich habe aber noch ein bisschen weiter geforscht und erste Ergebnisse erzielt, die mich hoffen lassen. Vielleicht hat ja jemand auf dieser Grundlage noch einen entscheidenden Tipp.

Aaaalso: ich habe mir ein kleines Beispielprogramm gebastelt. Dieses greift auf eine wie oben beschrieben von einer Kundendatenbank exportierte Abfrage zurück. Diese Abfrage enthält letztlich Artikeldaten zu ca. 85.000 Artikeln. In meinem kleinen Testprogramm gehe ich diese Daten nur einmal schnell durch und speichere von jedem Artikel die ID in einer Stringliste.

Folgender Code ist dem recht ähnlich, den ich auch in meinem eigentlichen Programm verwende:

Delphi-Quellcode:
procedure Tadospeed_main.ButtonRunSlowClick(Sender: TObject);

var currQuery: TADOQuery;
    i: integer;

begin
  IDList.Clear;
  i:=0;
  currQuery:=TADOQuery.Create(nil);
  currQuery.LoadFromFile(EditFilename.Text);
  while (not currQuery.Eof) do begin
    IDList.Add(currQuery.Fields[0].Value);
    inc(i);
    if i mod 1000=0 then begin
      LabelProgress.Caption:=IntToStr(i);
      Application.ProcessMessages;
    end;
    currQuery.Next;
  end;
  currQuery.close;
  currQuery.free;
end;
So, hier tritt das beschriebene Problem auf. Die ersten 20.000 Datensätze werden in einer knappen Sekunde verarbeitet (ich lasse mir ja den Fortschritt in einem Label anzeigen), danach wird es dann immer langsamer und langsamer.

Aufgrund dieses Verhaltens war meine Vermutung, dass jedes Mal wieder an den Anfang der Datenmenge zurückgesprungen und dann zum gewünschten Datensatz vorgegangen wird. Also irgendwas scheint da mit dem Zeiger schiefzulaufen.

Nun habe ich gesehen: Man kann ja auch direkt auf das "Recordset" zugreifen, ohne irgendwelche Sachen zu nutzen, die Delphi drumrum gebastelt hat. Gesagt, getan:

Delphi-Quellcode:
procedure Tadospeed_main.ButtonRunClick(Sender: TObject);

var currQuery: TADOQuery;
    i: integer;

begin
  IDList.Clear;
  i:=0;
  currQuery:=TADOQuery.Create(nil);
  currQuery.LoadFromFile(EditFilename.Text);
  while (not currQuery.Recordset.EOF) do begin
    IDList.Add(currQuery.Recordset.Fields.Item[0].Value);
    inc(i);
    if i mod 1000=0 then begin
      LabelProgress.Caption:=IntToStr(i);
      Application.ProcessMessages;
    end;
    currQuery.Recordset.MoveNext;
  end;
  currQuery.close;
  currQuery.free;
end;
Und siehe da: Plötzlich dauert das gesamte Verarbeiten der Daten noch nicht mal mehr eine Sekunde. Hmpf.

Das Problem scheint also das "Next" im Query zu sein. Wenn ich also im Recordset direkt mit MoveNext arbeite, dann klappt alles wunderbar. Problem ist nur: dann muss ich auch für das Einlesen mit dem Recordset arbeiten (siehe oben: also Recordset.fields, statt currQuery.Fields). Hier im Beispiel ist das egal, aber im echten Programm hätte das natürlich sehr aufwändige Umbaumaßnahmen zur Folge, da hier doch umfangreiche Datenstrukturen eingelesen werden.

Hat jemand eine Idee, wie man das zusammenbringen kann? Könnte ich der TADOQuery irgendwie klar machen, dass sich das Recordset durch mein MoveNext geändert hat und ich kann dann weiterhin die normalen Eigenschaften/Methoden zum Lesen benutzen?

Bis denn
Bommel
  Mit Zitat antworten Zitat
Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#6

AW: TADOQuery.LoadFromFile sehr langsam

  Alt 21. Jun 2012, 15:42
Zunächst würde ich dir ein
Delphi-Quellcode:
IDList.Items.BeginUpdate;
try
...
finally
  IDList.Items.EndUpdate;
end;
empfehlen. Dann probier nachmal das Befüllen aus.
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)
  Mit Zitat antworten Zitat
Bbommel

Registriert seit: 27. Jun 2007
Ort: Köln
655 Beiträge
 
Delphi 12 Athens
 
#7

AW: TADOQuery.LoadFromFile sehr langsam

  Alt 21. Jun 2012, 16:26
BeginUpdate/EndUpdate habe ich noch nie bei einer (nicht-visuellen) StringList gebraucht, habe es hier aber trotzdem mal getestet - ich greife ja nach jedem Strohhalm. Leider hat es am Ergebnis aber nichts geändert, d.h. das Verarbeiten ist genauso langsam wie vorher.

Hätte mich auch gewundert, denn in dem Beispiel von mir, in dem ich direkt mit dem "Recordset" arbeite, habe ich ja auch kein BeginUpdate/EndUpdate und die Liste ist in <1 Sek. gefüllt.

Hm. Mittlerweile habe ich auch die Hoffnung etwas aufgegeben und einige besonders zeit-empfindliche Stellen in meinem Code wie beschrieben umgebaut, so dass dieser Import nun so einigermaßen klappt.

Was meint ihr - kann man dieses ungünstige Laufzeitverhalten von Delphi denn als Bug interpretieren, den man mal melden sollte? (wobei vorher zu klären wäre, ob das in XE2 nicht schon besser läuft - wenn hier jemand Zeit/Lust hätte, das mit mir zu testen, kann er sich ja gerne melden)

Bis denn
Bommel
  Mit Zitat antworten Zitat
Iwo Asnet

Registriert seit: 11. Jun 2011
313 Beiträge
 
#8

AW: TADOQuery.LoadFromFile sehr langsam

  Alt 21. Jun 2012, 17:58
Aufgrund dieses Verhaltens war meine Vermutung, dass jedes Mal wieder an den Anfang der Datenmenge zurückgesprungen und dann zum gewünschten Datensatz vorgegangen wird. Also irgendwas scheint da mit dem Zeiger schiefzulaufen.
Wenn das so wäre, würde die Verlangsamung kontinuierlich sein. Du schreibst aber, das das so ab ca. 20.000 langsamer wird. Abrupt, oder wie?
  Mit Zitat antworten Zitat
Bbommel

Registriert seit: 27. Jun 2007
Ort: Köln
655 Beiträge
 
Delphi 12 Athens
 
#9

AW: TADOQuery.LoadFromFile sehr langsam

  Alt 21. Jun 2012, 18:28
Hiho,

das ist genau so - also die Verarbeitung wird immer langsamer. Ggf. war das ansonsten von mir missverständlich ausgedrückt. Ich habe mal ein kleines Video angefügt, bei dem man den Effekt ganz gut erkennen sollte.
Angehängte Dateien
Dateityp: zip 20120621_1823_05.zip (465,8 KB, 6x aufgerufen)
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 00:45 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