Autor Beitrag
Hans-Georg
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 23



BeitragVerfasst: Di 28.09.10 10:07 
Hallo
Ich suche mit SQL (Select) in einer Datenbank
da diese sehr groß ist möchte ich eine Fortschrittsanzeige
einbauen da der User meint das öfters nichts passiert geht
das auch bei SQL wenn ja wie

Danke im voraus
Hans-Georg
Nersgatt
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 1581
Erhaltene Danke: 279


Delphi 10 Seattle Prof.
BeitragVerfasst: Di 28.09.10 10:09 
Wenn Du die Datensätze nicht manuell sequenziell durchsuchst, wird das nicht gehen.
Meiner Erfahrung nach kann man langsame Datenbankabfragen meistens um den Faktor 10 (mindestens) beschleunigen, wenn man Designfehler behebt, Indizies richtig setzt und sauber programmiert.

_________________
Gruß, Jens
Zuerst ignorieren sie dich, dann lachen sie über dich, dann bekämpfen sie dich und dann gewinnst du. (Mahatma Gandhi)
Sinspin
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1336
Erhaltene Danke: 119

Win 10
RIO, CE, Lazarus
BeitragVerfasst: Di 28.09.10 10:28 
Das ist abhängig von der verwendeten Datenbank aber es geht. Wir verwenden hier in der Firma ADS, da gibt es entsprechende Callbackroutinen mit denen man eine Fortschrittsanzeige während langen SQL Statements anzeigen kann. Damit sind dann aber nicht generell Querys gemeint sondern eher andere komplexe aktionen wie indizieren oder packen.
Wenn eine Abfrage zu lange dauert hat men im Regelfall im Statement was unpassend zusammengebaut. Ändere zum Test einfach mal die Reihenfolge der Einschränkungen. Wenn du irgendwo mit oder arbeitest, teil die beiden Teile auf und fasse sie mit Union zusammen. Das hat bei mir machmal echte Wunder bewirkt.

_________________
Wir zerstören die Natur und Wälder der Erde. Wir töten wilde Tiere für Trophäen. Wir produzieren Lebewesen als Massenware um sie nach wenigen Monaten zu töten. Warum sollte unser aller Mutter, die Natur, nicht die gleichen Rechte haben?

Für diesen Beitrag haben gedankt: BenBE
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: Di 28.09.10 10:56 
Ich hoffe, dass du längere Texte mit Satzzeichen schreibst. :wink:
Callback wurde schon genannt und besseres Design ebenfalls.

Die Optimierung von DB-Abfragen kann man auch mit verschiedenen Tools hinbekommen. Bei Oracle geht das mit "Explain Plan". Wie das bei anderen DBs aussieht, kann ich dir nicht sagen.

Übliche Fehler:
- Fehlender Index
- Ungünstige Reihenfolge der Bedingungen im Where-Bereich
- Kreuztabellen
- Zu viele Datensätze (weitere Einschränkungen erforderlich)

Für diesen Beitrag haben gedankt: BenBE
Tranx
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 648
Erhaltene Danke: 85

WIN 2000, WIN XP
D5 Prof
BeitragVerfasst: Di 28.09.10 11:35 
Eigentlich ist das mit dem Einbinden einer Fortschrittsanzeige doch recht einfach, oder?

Du suchst in Recordcount Datensätzen von Anfang an (First) fortlaufend (Next).

dann gehe doch so vor:

ausblenden volle Höhe Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
// nur Programmteil, muss an die Gegebenheiten angepasst werden!!!

function Suche(was : string) : boolean;
var
  i, n : longint;
  gef : boolean;
  Fortschritt : TProgressbar;
begin
  gef := FALSE;
  with Datenbank do
  begin
    if not(active) then active := TRUE;
    n := Recordcount;
    if n=0 then 
    begin
      result := FALSE;
      exit;
    end;
    Fortschritt.Min := 0;
    Fortschritt.Max := n;
    Fortschritt.visible := TRUE;
    first;
    i := 0;
    gef := FALSE;
    while not(gef) and not(eof) do 
    begin
      Fortschritt.Position := i;      
       ... Routinen zur Suche, speichern in gef!
      inc(i);
      next;
    end;
  end;
  Fortschritt.visible := FALSE;
  result := gef;
end;


Wie gesagt, nur ein Programmfragment. So in etwa sieht es bei mir aus, wenn ich Datenbanken abfrage. Oft setze ich dann auch noch Disablecontrols und Enablecontrols, um die Abfrage zu beschleunigen.

Ich hoffe, gedient zu haben
Sinspin
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1336
Erhaltene Danke: 119

Win 10
RIO, CE, Lazarus
BeitragVerfasst: Di 28.09.10 16:01 
Ich denke, das ist voll am Problem vorbei.
Er sucht eine Möglichkeit um die Zeit zu überbrücken bis eine SQL Abfrage antwortet, also bis die Ausführung zum Programm zurückkehrt und die Ergebnismenge zum aubrufen bereitsteht.

_________________
Wir zerstören die Natur und Wälder der Erde. Wir töten wilde Tiere für Trophäen. Wir produzieren Lebewesen als Massenware um sie nach wenigen Monaten zu töten. Warum sollte unser aller Mutter, die Natur, nicht die gleichen Rechte haben?
Horschdware
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 744
Erhaltene Danke: 54

Win XP Pro, Win 7 Pro x64
Delphi 7, Delphi XE, C++ Builder 5, SAP R/3
BeitragVerfasst: Di 28.09.10 16:44 
Ich denke, man sollte erst einmal klären
a) wieviele Datensätze gelesen werden sollen
b) wieviele Datensätze derzeit tatsächlich gelesen / angefasst werden
c) wieviel Zeit das Ganze benötigt

Dann müsste man sich überlegen, ob diese lange Bearbeitungszeit überhaupt notwendig ist.
Wie schon erwähnt lassen sich viele Selects durch Umbau oder Optimierung beschleunigen.
Nächster Schritt: Select Statements genau unter die Lupe nehmen.

Ganz allgemein: Projektion und restriktion möglichst früh und vor Join ausführen

_________________
Delphi: XE - OS: Windows 7 Professional x64

Für diesen Beitrag haben gedankt: BenBE
alzaimar
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 2889
Erhaltene Danke: 13

W2000, XP
D6E, BDS2006A, DevExpress
BeitragVerfasst: Di 28.09.10 18:44 
user profile iconHorschdware hat folgendes geschrieben Zum zitierten Posting springen:

Ganz allgemein: Projektion und restriktion möglichst früh und vor Join ausführen

Ach, und ich dachte, genau anders herum. Oder ich habe dich misverstanden.

Kannst Du das anhand eines Beispieles erläutern?

Die Frage des Threadstellers impliziert, das der Server von vorneherein weiss, wieviele Daten er durchsuchen muss. Denn eine Fortschrittsanzeige ist nur dann möglich, wenn man vorher weiss, wieviel man zu durchsuchen hat.

Bei einer komplexen Abfrage ist das z.T. nicht deterministisch, d.h. am Anfang der Query nicht bekannt. Es kann auch sein, das ein Teil der Query eine externe Datenquelle beinhaltet.

Also: 'Richtige' RDBMS können das nicht. ADS ist nicht ganz so richtig, und eher (soweit ich mich entsinne) eine DBISAM mit SQL-Aufsatz. Ich kann mich dunkel erinnern, einmal damit gearbeitet, und etwas Ähnliches, wie eine Fortschrittsanzeige bei einer Query gesehen zu haben.

Aber nix gegen ADS.

_________________
Na denn, dann. Bis dann, denn.

Für diesen Beitrag haben gedankt: BenBE
Muck
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 98
Erhaltene Danke: 8

Win 8, Win 7, Vista, Win XP
Delphi XE3, Delphi 2009, Delphi 2007, Delphi 5
BeitragVerfasst: Di 28.09.10 19:52 
Hallo,

Oft vergisst man auch den LockType auf ReadOnly zu stellen und ein select auf eine groessere Tabelle (>500 MB) wird etwa 10 mal laenger dauern als mit einem ReadOnly Cursor. (z.B. bei ADO + MSSQL)

Sollte sich der select wirklich nicht optimieren lassen wie in den anderen Antworten beschrieben, dann waere eine Loesung unidirectional mit einem Server Cursor zu oeffnen solange man das Ergebnis nicht in einer grid anzeigen will.

Du kriegst dann die Kontrolle sofort zurueck und gehst mit eof Abfrage durch die Query. Waehrenddessen kannst Du dann die Fortschrittsanzeige (keine Prozentanzeige da Du RecordCount nicht kennst) laufen lassen.

Prior, First, Last ist dann nicht moeglich, ausserdem nicht RecordCount verwenden.

in Ado z.B.:

ausblenden Delphi-Quelltext
1:
2:
3:
ADOQuery1.CursorLocation:=clUseServer;
ADOQuery1.LockType:=ltReadOnly;
ADOQeury1.CursorType:=ctOpenForwardOnly;


Das ist ne Loesung fuer die Fortschrittsanzeige, aber dennoch beschaeftigst Du den SQL Server mit einer langen Abfrage, die wahrscheinlich vermeidbar ist.

Fuer TQuery
ausblenden Delphi-Quelltext
1:
Query1.undDirectional:=true;					


Markus

Für diesen Beitrag haben gedankt: BenBE