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