Autor Beitrag
DannyVapid
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 38


Delphi 5 Enterprise
BeitragVerfasst: Mi 06.10.04 11:03 
Hallo liebe DB-Kollegen,
folgender Sachverhalt:

in einer MySQL-Datenbank habe ich eine Artikeltabelle mit folgendem Aufbau:

- ID Int (Primary Key)
- ARTNR char(7) <- Index auf dieses Feld ist angelegt...
- ARTBEZ char(200)
u.v.a. Felder....

Mein Delphi-Programm greift z.Zt. per TTable auf diese Tabelle zu, IndexName ist auf den ARTNR-Index gesetzt.
In dem Hauptformular gibt es noch ein Edit1, mit dem ich nach der Artikelnummer suchen möchte.
Also folgender Code in das Edit1.OnChange-Event:

- Table1.FindKey([Edit1.Text])

... um bei jeder Änderung von Edit1 direkt in dem Schlüsselfeld zu suchen.
Klappt auch alles wunderbar! nur...
mittlerweile hat die Artikeltabelle knapp 1. mio Datensätze.
Das heisst um die TTable beim Start des Programms zu öffnen brauch ich schon ca. 15 Sekunden und das Programm greift sich dann auch erstmal ganz locker um die 100 MB an Arbeitsspeicher.

muss ich den "FindKey" nun wirklich so abbilden, daß ich bei jedem Edit1.OnChange eine Query schliesse, den Suchparameter neu setz und die Query wieder öffne?
oder gibt's vielleicht doch eine effizientere Möglichkeit?
Die Suchfunktionalität mit dem Edit-Feld muss auf jeden Fall erhalten bleiben.

danke für eure Hilfe
Danny
jasocul
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 6395
Erhaltene Danke: 149

Windows 7 + Windows 10
Sydney Prof + CE
BeitragVerfasst: Mi 06.10.04 11:13 
Suche mal in der OH unter Locate. Das könnte dein Problem lösen. Besser wäre es natürlich, wenn du die Datenmenge von vornherein reduzieren könntest. Sonst geht er im schlimmsten Fall durch die ganze Tabelle.
DannyVapid Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 38


Delphi 5 Enterprise
BeitragVerfasst: Mi 06.10.04 15:43 
Hallo Jasocul,

danke für die schnelle Antwort.
Leider kann ich die Datenmenge nicht reduzieren, denn ich muß ja im gesamten Artikelstamm suchen können.
TTable.Locate (ich denke das meintest Du) wird mich daher auch nicht weiterbringen, da es ja den Index der Tabelle schonmal garnicht benutzt.
Das ist aber auch nicht das Problem. Die Suche mittels TTable.Findkey funktioniert einwandfrei und auch sehr schnell.
Nur das Programm braucht aufgrund der grossen Datenmenge beim starten (also bei TTable.Open) sehr lange und allokiert sehr viel Arbeitsspeicher (zu sehen im Task-Manager). ich denke einfach es cached das Indexfeld beim öffnen der Tabelle, hmmmmm.

denke ich muss von der TTable-Komponente weg, nur find ich die FindKey-Methode doch so edel und prima schnell.
sollte eine MySQL-Datenbank das nicht auch anders hinkriegen?
vielleicht hast Du oder jemand anders noch eine Idee.

Trotzdem danke nochmal
Danny
jasocul
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 6395
Erhaltene Danke: 149

Windows 7 + Windows 10
Sydney Prof + CE
BeitragVerfasst: Mi 06.10.04 15:58 
Ich hatte das nicht ganz klar ausgedrückt. Du sollst TQuery.Locate mal ausprobieren.
TQuery hat den Vorteil, dass nicht zwingend die ganze Tabelle geladen wird.
greg
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 119

Windows2000, WindowsXP
D5 Prof
BeitragVerfasst: Mi 06.10.04 16:03 
Hallo Danny,

wenn Du eine TQuery Komponente einsetzen willst, gehört die ARTNR in die where Bedingung. Ich denke einen Veruch ist es Wert, ob die Datenbank damit schneller zurecht kommt.

Bei der Beschreibung der Struktur Deiner Artikeldatenbank steht am Ende u.v.a Felder ...
Die Breite der Tabelle hat auch einen Einfluss auf die Performance. Vielleicht lassen sich die Daten ja auch auf mehrere Tabellen verteilen, je nachdem, welche Daten Du jeweils brauchst. Du könntest unter Umständen wiederkehrende Einträge auch in eigenen Tabellen verwalten und über die ID's die Werte auslesen. Das Konstrukt wird dadurch nicht einfacher aber evtl. deutlich schneller und weniger speicherhungrig.

Gruß
Gregor
grayfox
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 800

win98, winXP
D4 Standard; D6 Personal
BeitragVerfasst: Mi 06.10.04 16:03 
ich hab zwar die vorherigen beiträge nur kurz überflogen - aber was spricht dagegen, gleich eine TQuery anstatt eines TTables zu verwenden?
greg
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 119

Windows2000, WindowsXP
D5 Prof
BeitragVerfasst: Mi 06.10.04 16:13 
... da ist mir doch glatt noch etwas aufgefallen ...

Die ARTNR sollte Primärschlüssel sein. Auch wenn es mit einer ID im Integer Format so schön einfach ist, ist das eigentlich überflüssiger Balast.

Gruß
Gregor
DannyVapid Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 38


Delphi 5 Enterprise
BeitragVerfasst: Mi 06.10.04 16:21 
Hallo Greg,

die Artikeltabelle ist schon gut normalisiert, hab mich mit "u.v.a. Felder" nicht gerade geschickt ausgedrückt.
Es sind nur 6 Felder insgesamt, alles weitere habe ich schon in Detailtabellen ausgelagert.

Hi Grayfox,

also meine Vorstellung ist ich habe auf meinem Formular ein DBGrid, welches mir die komplette Artikeltabelle anzeigt (das macht es ja im Moment auch via einer TTable, wie beschrieben).
unter dem Grid liegt ein TEdit, mit diesem möchte ich nach der Artikelnummer suchen können (also nach dem Index).
Also in das Event TEdit.OnChange kommt rein:

TTable.FindKey([Edit1.Text]);

Sobald ich eine vorhandene ArtikelNr in das TEdit eintippe...schwupps...springt das Grid mir auf den passenden Datensatz.

Wie könnt ich denn genau diese Funktionalität mit einer TQuery umsetzen? da bin ich bisher noch nicht hintergekommen.. Bei TQuery gibt's ja (logischerweise) keine FindKey-Methode.
grayfox
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 800

win98, winXP
D4 Standard; D6 Personal
BeitragVerfasst: Mi 06.10.04 17:41 
hallo danny!

zunächst mal schöne grüsse nach berlin ;)

bei einer änderung vom TTable zu einer TQuery ändert sich an deinem formular und an deinem edit-feld gar nichts.

probiert zunächst mal in der IDE aus.

- TQuery aufs form ziehen
- database eintragen
- datasource mit TQuery verbinden
- im property 'Strings' eintragen 'SELECT * FROM DeinTabellenname'

sobald du nun im OI bei deiner Query 'active' auf 'true' stellst, solltest du schon den tabelleninhalt angezeigt bekommen.

um nach einer oder mehreren artikelnummern zu suchen, legst du dir am besten einen formatstring. der vorteil zur parameterübergabe liegt darin, dass man auch die felder, nach denen gesucht werden soll, variabel gestalten kann.

und in die procedure Edit1Exit oder SuchBtnClick kommt der folgende code:
(annahme: deine Query heisst ArtikelQuery)

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
var
  cSql: String;
  SqlString: String;

begin
  cSql:= 'SELECT * FROM DeinTabellenname (WHERE ArtikelNr = "%s")'
  
  SqlString:= Format(cSql,[Edit1.Text]);
  with ArtikelQuery do begin
    Close;
    SQL.Clear;
    SQL.Add(SqlString);
    Open
  end;
end;


und in der procedure FormClose deines formulares überprüfen, ob die query aktiv ist und ggf schliessen.
du kannst auch eine lösung mit jokern anbieten - zb das Edit-Feld immer mit einem '*' vorbelegen und bekommst so alle datensätze angezeigt, wenn du

1) deinen cCSL-string wie folgt änderst:
ausblenden Delphi-Quelltext
1:
(WHERE ArtikelNr LIKE "%s")					


2) vor dem zuweisen des Edit-Textes alle darin vorkommenden '*' in '%' und '?' in '_' änderst.

im file localsql.hlp, welches sich in deinem verzeichnis BDE befindet, findet du zusätzliche infos über SQL & konsorten ;)

wie du siehst, gar keine hexerei und bestimmt um einiges schneller als die lösung mit einem TTable.

mfg, stefan

//edit:

du startest deine suche im 'TEdit.OnChange '? :gruebel:
d.h. nach jeder eingabe eines zeichens läuft die suchroutine, auch bei falschen eingaben, da der user/ die userin gar keine gelegenheit hat, die eingabe noch richtigzustellen...

daher bevorzuge ich die lösung im OnExitEvent bzw den start mit einem eigenen button.
DannyVapid Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 38


Delphi 5 Enterprise
BeitragVerfasst: Do 07.10.04 09:49 
Hallo Stefan!

Danke für Deine ausführlichen Erläuterungen.
Deine Lösung funktioniert natürlich super, nur ist die Optik des Programms dann etwas geändert, weil nach Ausführung der Suche eben nur der/die Ergebnissätze zurückgeliefert werden.

Die Suche hatte ich absichtlich ins OnChange gesetzt, weil TTable.Findkey bei einem falschen (oder unvollständigem) Schlüssel einfach garnichts umpositioniert.
d.h. sobald ich eine gültige ArtNr. in mein TEdit tippe erfolgt sofort der Sprung auf den Satz, ansonsten passiert nichts. das fand ich ja gerade so elegant.

OK, nu werd ich damit leben, das es eben in Zukunft etwas anders aussieht. Auch nur gewöhnungssache, naja.

Also dann vielen Dank und schöne Grüsse nach Litschau
Danny