AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Sprachen und Entwicklungsumgebungen Sonstige Fragen zu Delphi Delphi SQL-Abfrage im Thread und füllen eines ListView

SQL-Abfrage im Thread und füllen eines ListView

Ein Thema von Captnemo · begonnen am 28. Sep 2011 · letzter Beitrag vom 29. Sep 2011
Antwort Antwort
Seite 1 von 3  1 23   
Benutzerbild von Captnemo
Captnemo

Registriert seit: 27. Jan 2003
Ort: Bodenwerder
1.126 Beiträge
 
Delphi XE4 Architect
 
#1

SQL-Abfrage im Thread und füllen eines ListView

  Alt 28. Sep 2011, 15:02
Hallo Leute,

ich schlage mich jetzt schon einen ganze Weile mit einem mit einem Problem rum, für das ich jetzt nur noch eine Lösung sehe: Threads.

Hier mal zum Problem. Ich habe eine Art Terminplanungsprogramm in dem man Termine für bestimmte Ressourcen verwalten kann. Wenn ich dann einen Termin aufrufe, werden dort die Termindetails dargestellt und eine Historie für die ausgewählte Ressource angezeigt. Alles Funktioniert fehlerfrei, nur die Abfrage der Historie wird bei längerer Laufzeit des Programms ein Zeitfaktor. Der Grund dafür ist klar, denn wenn dann mit der Zeit so 40000 Termine eingetragen sind, und für die Historie eine SQL-Abfrage abgesetzt wird, benötigt der SQL-Server schon allein 5-7 Sekunden um die Daten bereit zu stellen.
Leider wartet das Prog ja nach dem Query1.active:=True eben auf die Rückmeldung des Query's (ich verwende ZEOS und MySQL) bevor es dann mit dem Füllen des ListView weitergeht. Letzterer Schritt ist dann wieder uneingeschränkt schnell.

Mein einziger erfolgversprechende Lösungsansatz wäre es, die SQL-Abfrage in einen Thread auszulagern, von diesem dann nach dem Anzeigen der Terminform unabhängig von Usereingaben das Listview füllen zu lassen.
So fällt für den User die Wartezeit nicht mehr so deutlich auf, und im Listview könnte man solange ein "Daten werden abgerufen..." darstellen.

So weit so gut. Aber wie fange ich das an. Leider hab ich von Threads recht wenig Ahnung und alle Tutorials und Bespiele beschränken sich leider auf recht simple Dinge wie eine String übergeben oder ein paar Werte zu berechnen.

Meine erste Frage in diesem Zusammenhang, muß ich für einen Thread eine extra Unit verwenden, oder kann ich das in meiner Termin Unit mit unterbringen?

Die zweite Frage wäre, kann ich aus einem Thread einfach per uses mein Datamodul einbinden und auf die Querys und die Connection zugreifen?

Kann mein Thread dann einfach so auf das Listview zugreifen?

Wie gesagt, ich hab von Thread wenig Ahnung, und ein Tutorial was mir diese Fragen beantwortet hab ich leider noch nicht gefunden.
Dieter
9 von 10 Stimmen in meinem Kopf sagen ich bin nicht verrückt. Die 10. summt dazu die Melodie von Supermario Bros.
MfG Captnemo
  Mit Zitat antworten Zitat
Benutzerbild von Bernhard Geyer
Bernhard Geyer

Registriert seit: 13. Aug 2002
16.641 Beiträge
 
Delphi 10.2 Tokyo Professional
 
#2

AW: SQL-Abfrage im Thread und füllen eines ListView

  Alt 28. Sep 2011, 15:09
Der Grund dafür ist klar, denn wenn dann mit der Zeit so 40000 Termine eingetragen sind, und für die Historie eine SQL-Abfrage abgesetzt wird, benötigt der SQL-Server schon allein 5-7 Sekunden um die Daten bereit zu stellen.
Ist die Datenmenge so groß das es so lange dauert? Sollte normalerweis in << 1s möglich sein wenn Bandbreite genügend da ist bzw. Server korrekt konfiguiert. Evtl. nicht alle Detaildaten laden die man eh nicht sofort sieht.

Mein einziger erfolgversprechende Lösungsansatz wäre es, die SQL-Abfrage in einen Thread auszulagern, ...
Sollte kein Problem sein. Manche DB-Zugriffskompos erfordern das du dann auch im Thread eine eigene Connection hast.

... von diesem dann nach dem Anzeigen der Terminform unabhängig von Usereingaben das Listview füllen zu lassen
Die Listview wirst du nicht über den Thread füllen können da die VCL bzw. die zugrunde liegenden Win-Controls eine Thread-Affinität haben. Du darfst sie nur im erzeugenden Thread verwenden.

Sinnvoller ist hier die Daten en block/blockweise zurück an die Hauptapp zu geben und dann die Listview im Virtual Modus zu betreiben.
Windows Vista - Eine neue Erfahrung in Fehlern.
  Mit Zitat antworten Zitat
Benutzerbild von Union
Union

Registriert seit: 18. Mär 2004
Ort: Luxembourg
3.307 Beiträge
 
Delphi 7 Enterprise
 
#3

AW: SQL-Abfrage im Thread und füllen eines ListView

  Alt 28. Sep 2011, 15:15
Genau, hol doch nur die 10..100 neuesten History-Einträge pro Ressource und mach wenn der Benutzer weiter nach unten blättert ein Refresh auf alle. Oder einen Button "Alle Anzeigen"
Ibi fas ubi proxima merces
sudo /Developer/Library/uninstall-devtools --mode=all
  Mit Zitat antworten Zitat
webcss

Registriert seit: 10. Feb 2006
255 Beiträge
 
Delphi XE2 Professional
 
#4

AW: SQL-Abfrage im Thread und füllen eines ListView

  Alt 28. Sep 2011, 15:16
Für eine genaue Antwort müsste ich ein wenig in meiner "Krabbelkiste" kramen, aber aus dem Kopf soviel:

Du erstellst deinen nebenläufigen Thread. Dieser *muss* eine eigene Verbindung aufbauen (Database, Transaction + Query!), er darf nicht die Verbindung des MainThread benutzen sonst knallt's.

Den startest Du mit deiner Abfrage und lässt in nebenher dudeln. Wenn das Abfrageergebnis komplett ist, terminiert sich der Nebenthread idealerweise selbst.

Um die Performance zu steigern, solltest du die ListView im VirtualMode (siehe OnData der ListView) einsetzen.

Gruß
Clemens
"Wer seinem Computer Mist erzählt, muss immer damit rechnen..." (unbekannt)
"Der Computer rechnet damit, dass der Mensch denkt..." (auch unbekannt)
mein blog
  Mit Zitat antworten Zitat
Benutzerbild von Captnemo
Captnemo

Registriert seit: 27. Jan 2003
Ort: Bodenwerder
1.126 Beiträge
 
Delphi XE4 Architect
 
#5

AW: SQL-Abfrage im Thread und füllen eines ListView

  Alt 28. Sep 2011, 16:13
Ist die Datenmenge so groß das es so lange dauert? Sollte normalerweis in << 1s möglich sein wenn Bandbreite genügend da ist bzw. Server korrekt konfiguiert. Evtl. nicht alle Detaildaten laden die man eh nicht sofort sieht
Naja, ich hab festgestellt, dass die Abfrage bei 40000 DS schon so an die 4,6 Sekunden rankommt. Das sind die gesammelten Termine der letzten 3 Jahre. In weiteren 3 Jahren sind es schon 80000 DS und ich denke nicht, dass sich der Zeitbedarf linear zu DS-Anzahl verhält. aber das könnte man ja ausprobieren.

Ich habe auch erst gedacht es länge an meiner Anwendung, aber als ich dann direkt mit dem MySQL-Adminstrator die gleichen Zeiten gemessen habe, denke ich mir das es wohl weniger an meiner Anwendung zu tun hat.

So, ich werd das mal probieren mit ein thread.

Aber meine erste Frage ist noch offen. Kann ich in der Terminunit einfach mit
Code:
Type
   MyThread = TThread
   end;
den Thread mit einfügen, oder muß dafür eine eigene Unit existieren?

wie ich die Daten an die Hauptapp zurückgeben weiß ich auch noch nicht, aber einen Schritt nach dem anderen.
Dieter
9 von 10 Stimmen in meinem Kopf sagen ich bin nicht verrückt. Die 10. summt dazu die Melodie von Supermario Bros.
MfG Captnemo
  Mit Zitat antworten Zitat
Benutzerbild von jfheins
jfheins

Registriert seit: 10. Jun 2004
Ort: Garching (TUM)
4.539 Beiträge
 
#6

AW: SQL-Abfrage im Thread und füllen eines ListView

  Alt 28. Sep 2011, 17:27
Aber meine erste Frage ist noch offen. Kann ich in der Terminunit einfach mit
Code:
Type
   MyThread = TThread
   end;
den Thread mit einfügen, oder muß dafür eine eigene Unit existieren?
Ja, das sollte ohne Probleme gehen. Die eigentliche Arbeit übernimmt ja die Klasse.
Zitat:
wie ich die Daten an die Hauptapp zurückgeben weiß ich auch noch nicht, aber einen Schritt nach dem anderen.
Z.B. ein Array of record erstellen (der record enthält schon genau die felder, die später in die Spalten der Listview kommen) und dann das zurückgeben.

Mal ne andere Frage: Was genau dauert lange? Wenn du von den 40.000 Datensätzen einen auswählst, das abrufen der History oder das übertragen der Daten? Ich bin mir ziemlich sicher dass das schneller gehen muss. Vll. keine Indizies gesetzt? Falsche indizes?
  Mit Zitat antworten Zitat
Benutzerbild von Captnemo
Captnemo

Registriert seit: 27. Jan 2003
Ort: Bodenwerder
1.126 Beiträge
 
Delphi XE4 Architect
 
#7

AW: SQL-Abfrage im Thread und füllen eines ListView

  Alt 28. Sep 2011, 17:49
Tja, was das explizit so lange dauert kann ich dir nicht genau sagen.
Ich habe versucht das ganz mit Indizies versucht, aber ich habe dadurch keine nennenswerten Verbesserungen festgestellt. Ich mir sogar ein View erzeugt, welches nur die Felder enthält (sind glaub ich 6), aber auch wenn ich das abfrage, bekommen ich keine Geschwindigkeitssteigerung.

Die Tabelle dir ich abfrage hat so 49 Felder, davon sind 2 Blob's der Rest String, Int und Datetime. Die beiden Blob's verwende ich einmal für die Ablage von Richtext und das andere für eine kleine Grafik 20x50 Pixel, welche aber nur bei den wenigsten DS tatsächlich gefüllt ist.

In der View sind aber nur Datetime, String und int.

Ich habe auch schon die Speichergrenzen in den Variablen des MySQL-Server angehoben, auch keine nennenswerten veränderungen. Wenn ich einen einzelnen DS über Lfdnr (primärindex) abfrage, geht das sehr schnell.

Ich hab auch schon mal hier im Forum gefragt, wie MySQL den zu verwendeten Index auswähl. Da hieß es, wenn er existiert wird er automatisch verwendet. Ich weiß aber nicht, ob das stimmt.

Beim Thread habe ich so meine Probleme. Da ich im Thread ein eigene Connection- und Query-Object verwenden soll, muß ich diese ja auch erst einmal erzeugen. Das kann aich aber nicht in der procedure Execute machen, sonder eher in einer Create. Gibt's die auch in einem Thread? Wenn ich in D7 über Datei-Neu-Weitere eine TThread-Unit anlege, dann gibt es dort keine Create-procedure. Und wenn ich eine anlege, dann meckert der Compiler.

Grundsätzlich ist mir jede Lösung recht. Ohne TThread wär's an dieser Stelle einfacher. Andererseits würd ich gerne auch mal endlich diesen TThread-Kram verstehen. Steh da irgendwie auf einem Schlauch.
Dieter
9 von 10 Stimmen in meinem Kopf sagen ich bin nicht verrückt. Die 10. summt dazu die Melodie von Supermario Bros.
MfG Captnemo
  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
 
#8

AW: SQL-Abfrage im Thread und füllen eines ListView

  Alt 28. Sep 2011, 20:41
Jede (wirklich jede) Klasse hat eine Constructor und der heißt auch eigentlich Create.

Wenn der Compiler meckert, dann, weil die Klasse abgeleitet wurde (die ist immer abgeleitet, min. von TObject) und im Vorfahr etwas anders deklariert war, bzw. du das mit dem inherited oder inherited Create so nicht passt.

Hilfreich dazu ist es sich die Vorfahr-Klasse mal anzuschauen, dann sieht man auch, wie der Constructor da aussieht

Ansonsten kann ich nur mal den Tip geben, im interface-Teil der neu zu erstellenden Klasse mal Strg-Leertaste zu drücken und dann wundern was da so auftaucht
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
FredlFesl

Registriert seit: 19. Apr 2011
293 Beiträge
 
Delphi 2009 Enterprise
 
#9

AW: SQL-Abfrage im Thread und füllen eines ListView

  Alt 28. Sep 2011, 21:24
Wieso musst Du eigentlich alle 40.000 Einträge anzeigen?
Wie ich das machen würde?
Fetch-on-Demand. Ich lade mir 1000 oder so Einträge, und wenn jemand nach unten scrollt und den 1001sten sehen will, lade ich den nächsten Happen ein. Die Happen (1000 oder so) sind so gewählt, das das Laden sehr schnell geht.

Die Query sieht immer gleich aus:
Code:
select first 1000 * from MyView where SortColumn>:LastColumn
Und der Parameter :LastColumn enthält den Wert der Spalte 'SortColumn' des jeweils untersten Eintrags der breits geladenen Daten.

Eigentlich keine große Sache. Kann aber sein, das dann die Query selbst lahm wird (wenn man die DB nicht richtig gepimpt hat).
Das Bild hängt schief.
  Mit Zitat antworten Zitat
Medium

Registriert seit: 23. Jan 2008
3.596 Beiträge
 
Delphi 2007 Enterprise
 
#10

AW: SQL-Abfrage im Thread und füllen eines ListView

  Alt 28. Sep 2011, 22:41
Wir haben das SQL Statement zwar nie gesehen bisher (das, und die Tabellendefinition wären nicht ganz unnützlich beim Analysieren hier ), aber ich schmeisse zudem auch einfach mal in den Raum, dass Volltextsuchen der Art "LIKE '%substr%'" jeden Index aushebeln, und öfter mal Ursache für Performanceprobleme sind. Zeig doch mal das SELECT, sowie das aus der Tabelle erzeugte CREATE Statement her. 40k Sätze sind eigentlich nicht wirklich eine große Sache, ausser dein Server geht über eine eher mäßig schnelle Verbindung. Danach wurde übrigens auch schon gefragt: Ist der Server lokal, oder eine andere Maschine? Wenn letzteres: Wie ist er an deinen Client angebunden?
"When one person suffers from a delusion, it is called insanity. When a million people suffer from a delusion, it is called religion." (Richard Dawkins)
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 3  1 23   

Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche
Ansicht

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 10:18 Uhr.
Powered by vBulletin® Copyright ©2000 - 2020, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2020 by Daniel R. Wolf