Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Datenbanken (https://www.delphipraxis.net/15-datenbanken/)
-   -   Abfrage mit Query schnell in TStringlist importieren (https://www.delphipraxis.net/178201-abfrage-mit-query-schnell-tstringlist-importieren.html)

norwegen60 23. Dez 2013 11:28

Datenbank: MsSQL • Version: 2008 • Zugriff über: UniDac, ADO

Abfrage mit Query schnell in TStringlist importieren
 
Hallo zusammen,

hin und wieder benötige ich Daten einer DB in einer TStringlist. Gibt es neben
Delphi-Quellcode:
  while not UniQuery1.eof do
  begin
    slDB.Add(UniQuery1.Fields[0].AsString);
    UniQuery1.next;
  end;
eine Möglichkeit, mit der ich die Ergebnismenge direkt in eine TStringlist übernehmen kann. Obiger Code dauert ca. 0.06s per Datensatz => bei nur 1000 Datensätzen 60s


Hintergrund:
Große MsSQL Tabelle mit ca. 2 Mio Datensätzen
Auswahl über Pulldownliste mit Autovervollständigung
Wunsch, in Pulldownliste auch per Cursor rauf/runter blättern zu können
Liste sollte aber aktuelle Daten enthalten, wenn andernorts Daten eingegeben wurden (Refresh direkt beim Start der Einagbe würde mehrere s Dauern, egal wie Fetchall gesetzt ist)
Bisher verwendet: TDBLookupComboPlus, welche mit kleinen Datenmenge auch super funktioniert mit Möglichkeit per Rechtsklick Daten zu aktualisieren
Problem: Kunden möchten weiterhin auch einfach nur in der Pulldownliste per Cursor runter blättern können


Danke
Gerd

Furtbichler 23. Dez 2013 12:59

AW: Abfrage mit Query schnell in TStringlist importieren
 
Zitat:

Zitat von norwegen60 (Beitrag 1240843)
Obiger Code dauert ca. 0.06s per Datensatz => bei nur 1000 Datensätzen 60s

. Das kann nicht sein. Das ist viel zu langsam. Ich schaffe es, hunderttausend Daten in unter einer SEkunde einzulesen. Schreib mal ein 'DisableControls/'EnableControls um die Schleife. Und dann vielleicht noch den Zugriff auf das Feld optimieren:
Delphi-Quellcode:
Var
  field : TField;

Begin
  field := UniQuery1.Fields[0];
  UniQuery1.DisableControls;
  try
    while not UniQuery1.eof do
    begin
     slDB.Add(field.AsString);
     UniQuery1.next;
    end;
  finally
    UniQuery.EnableControls;
  End
End;
Wie soll die Autovervollständigung denn laufen? Wie sehen die Strings in der Tabelle aus? Ist Budget vorhanden? Ich würde mir dann die DevExpress-Komponentensammlung besorgen, die haben das alles schon eingebaut.

Jasocul 23. Dez 2013 13:19

AW: Abfrage mit Query schnell in TStringlist importieren
 
Bei so einer Anwendung und bei der Geschwindigkeit vermute ich eine sortierte StringList.
Die Sortierung sollte besser abgeschaltet sein und die Datensätze schon sortiert aus der Datenbank gelesen werden.

DisableControls wurde ja schon erwähnt.

Eventuell solltest du eine Messung machen, wie lange es dauert, einfach die Datensätze in einer Schleife nur zu durchlaufen, ohne etwas zu machen. Damit kann man zumindest prüfen, ob die Ursache bei der Datenbank oder bei der Verarbeitung zu suchen ist.

Bernhard Geyer 23. Dez 2013 14:38

AW: Abfrage mit Query schnell in TStringlist importieren
 
Ich halte den Designansatz für falsch.

1. Die Daten in TStringlist zu kopieren ist vollkommen unnötige Arbeit. Hier kann man mit dem Virtuellen Modus von StringList oder ListView besser arbeiten

2. Mio. Daten zum Client zu übertragen und dann eh nur 20-50 effektiv anzuschauen ist nicht zielgerichtet. Lade immer nur sagen wir 500 Datensätze und die anderen Features solltest du besser dahingehend machen das du hier kleine angepasste Queries an die DB schickst.

norwegen60 25. Dez 2013 11:57

AW: Abfrage mit Query schnell in TStringlist importieren
 
Hallo zusammen,

Danke für die schnellen Antworten. Hab die Ursache gefunden.

Es war nicht das 'DisableControls/EnableControls' sondern dass ich direkt ein ADD() auf die Stringlist einer TColumnBox von TMS gemacht habe. Sortierung war ausgeschalten.
Wenn ich selber eine Stringlist deklariere dauert es noch ca. 0.02s für 1000 Datensätze.

Im Grund genommen ist es mir auch klar, dass es effektiver wäre nur mit einem Teil der Daten zu arbeiten. Deshalb habe ich auch viel Versuche mit Fetchall und den verschiedenen anderen Parametern in der UniDac-Query gemacht.

Wenn es beim Eintippen einer Nummer aber schon "nur" 100ms dauert, bis der Cursor weiterspringt ist das für Schnelltipper nervig. Und ich glaube nicht mehr dran, dass ich per SQL schnellere Abfragezeiten erreiche. Deshalb jetzt meine Versuche, die Auswahl-Daten (1 oder 2 Felder und nur bei den großen Tabelle) komplett lokal zu holen um dann wesentlich schneller damit arbeiten zu könne. Sobald der richtige Datensatz festgelegt ist, hol ich mir dann alle benötigten Felder oder verknüpfte Tabellen von der DB.

Virtualmode und DevExpress schau ich mir auch mal an

Danke
Gerd

himitsu 25. Dez 2013 13:44

AW: Abfrage mit Query schnell in TStringlist importieren
 
Auch die TColumnBox sollte sowas wie DisableControls haben, was man dabei aktivieren sollte.

Ansonsten erstmal in eine TStringList und das dann komplett an die TColumnBox übergeben.

Uwe Raabe 25. Dez 2013 16:14

AW: Abfrage mit Query schnell in TStringlist importieren
 
Zitat:

Zitat von norwegen60 (Beitrag 1240996)
Wenn es beim Eintippen einer Nummer aber schon "nur" 100ms dauert, bis der Cursor weiterspringt

Es stellt sich hier doch die Frage, ob dem User bei jedem Tastendruck eine aktualisierte Cursor-Position angezeigt werden muss. Eigentlich gibt es ja nur zwei Szenarien: 1. der User gibt einen String (z.B. eine Nummer) ein, den er schon kennt und erwartet danach das Ergebnis oder 2. der User drückt eine Taste und entscheidet anhand der Anzeige, welche Taste er als nächstes drückt. Im ersten Fall ist die konstante Aktualisierung unnötig und im zweiten Fall ist die Wahrscheinlichkeit hoch, daß der Entscheidungsprozess länger dauert als die Abfrage und Anzeige der benötigten (das sind ungefähr die sichtbaren) Datensätze. Die Echtzeit-Navigation in Tabellen mit zigtausend Datensätzen ist ein Relikt aus alten BDE-Zeiten, das man schleunigst ablegen sollte.

Furtbichler 25. Dez 2013 16:57

AW: Abfrage mit Query schnell in TStringlist importieren
 
Wie soll das denn aussehen? Willst Du tippen und unter dem Eingabefeld ist eine Liste mit ca. 8-10 Einträgen, wobei der erste Eintrag markiert ist, der mit den von dir eingetippten Zeichen übereinstimmt (Incremental Search)? Oder sollen nur die angezeigt werden, die deinem Suchkriterium entsprechen (Filter)?

Beides würde ich nicht mit einer Combobox lösen, die ist dafür einfach nicht gemacht. Versuch dein Glück mit einer Komponente, die einen 'virtuellen Modus' hat, d.h. die sich die Daten bei Bedarf abholt. Beispiele sind TListBox mit 'ListBox.Style := lbVirtual' oder eine TListView mit 'OwnerData := True'


Alle Zeitangaben in WEZ +1. Es ist jetzt 18:08 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