Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Datenbanken (https://www.delphipraxis.net/15-datenbanken/)
-   -   Delphi Optimieren der Datenbankabfragen für Reportpipelines (https://www.delphipraxis.net/139977-optimieren-der-datenbankabfragen-fuer-reportpipelines.html)

erich.wanker 9. Sep 2009 14:22

Datenbank: Firebird • Version: 2.1.0 • Zugriff über: ZEOS

Optimieren der Datenbankabfragen für Reportpipelines
 
Hallo Leute,

Situation:
WinXP / Delphi 7 / Firebird 2.1 / Zeos / Reportbuilder 9.0

Eine GDB Datei mit ca 30 Tabellen...
Tabelle 1: Kunden
Tabelle 2: Details
Tabelle 3: Arbeiten
Tabelle 4: Arbeitsbeschreibung
Tabelle 5: Beschreibungdokumente
...



Beispiel Datenstruktur:
Delphi-Quellcode:
Kunde1
     Detail 1
         Arbeit 1
         Arbeit 2
         Arbeit 3
             Arbeitsbeschreibung 1
                Beschreibungsdokument 1
                Beschreibungsdokument 2
     Detail 2
         Arbeit 1
         Arbeit 2
     Detail 3
     Detail 4
         Arbeit 1
             Arbeitsbeschreibung 1
Kunde 2
....
Wenn ich nun Daten via Reportbuilder drucken will geh ich folgendermaßen vor:

Tabelle1 - afterScroll .. Select * from Tabelle 2 where tabelle2.Verknüpft_mit = tabelle1.aktuelleNummer
Tabelle2 - afterScroll .. Select * from Tabelle 3 where tabelle3.Verknüpft_mit = tabelle2.aktuelleNummer
Tabelle3 - afterScroll .. Select * from Tabelle 4 where tabelle4.Verknüpft_mit = tabelle3.aktuelleNummer
Tabelle4 - afterScroll .. Select * from Tabelle 5 where tabelle5.Verknüpft_mit = tabelle4.aktuelleNummer

.. jede Tabelle hat eine Pipeline, die ich dann via Subreports zu Papier bringe ..

aber das dauert ! ... kann ich (die Tabellenstruktur muss ich belassen wie sie ist) .. durch irgendeine andere Art der Datenselektierung das ganze schneller machen ... ? im Moment werden ja extrem viele SQL Statements gefeuert, wenn der Reportbuilder durch die Tabellen fährt .. kann ich was mit Bookmarks machen oder so ?

Vielen Dank

Erich

mkinzler 9. Sep 2009 14:50

Re: Optimieren der Datenbankabfragen für Reportpipelines
 
-kein Select *
-Wie sihet es mit den Indizes aus?
-SP

erich.wanker 9. Sep 2009 14:56

Re: Optimieren der Datenbankabfragen für Reportpipelines
 
hi,

-kein Select *
via reportdesigner könnte edes x-beliebige feld gedruckt werden .. ich kann nicht im vorfeld definieren, welche.

-Wie sihet es mit den Indizes aus?
indizes hab ich nur eine interne nummer, sonst nix

SP? ..

hoika 9. Sep 2009 15:04

Re: Optimieren der Datenbankabfragen für Reportpipelines
 
Hallo,

jedes Feld eines where biw. join wird indiziert.
Das wären also mind. Verknüpft_mit und aktuelleNummer

Ausserdem sollte die Endung nicht GDB heissen,
besonders unter XP nicht.
XP erzeugt bei jedem Öffnen eine "Sicherheitskopie".


Heiko

nahpets 9. Sep 2009 15:07

Re: Optimieren der Datenbankabfragen für Reportpipelines
 
Hallo,

beim Einsatz von TTable könnte das in der Form funktionieren:

Delphi-Quellcode:
Table2.Filtered := False;
Table2.Filter  := 'id = ' + Table1.FieldByName('ID').AsString;
Table2.Filtered := True;
Table3.Filtered := False;
Table3.Filter  := 'id = ' + Table1.FieldByName('ID').AsString;
Table3.Filtered := True;
Table4.Filtered := False;
Table4.Filter  := 'id = ' + Table1.FieldByName('ID').AsString;
Table4.Filtered := True;
Table5.Filtered := False;
Table5.Filter  := 'id = ' + Table1.FieldByName('ID').AsString;
Table5.Filtered := True;
d. h.: Jede der Detailtabellen enthält alle Daten (müsste bei Querys auch gehen) und beim Scrollen wird der Filter auf den entsprechenden Fremdschlüssel gesetzt.

Alternativ schau Dir mal Table1.Lookup() an, immer davon ausgehend, dass Zeos entsprechende Implementierungen enthält.
Eventuell könnte auch noch Table1.SetRange eine Alternative sein.

Und: Wie sieht die Datenmenge aus, gibt es jeweils für die Schlüssel einen passenden Index? (Das bitte zuerst abklären, kann extrem zur Beschleunigung beitragen.)
Der Index auf die interne Nummer ist das der Index auf Verknüpft_mit und aktuelleNummer, wenn nicht, bitte unbedingt diese Spalten mit 'nem Index versehen.

erich.wanker 9. Sep 2009 15:37

Re: Optimieren der Datenbankabfragen für Reportpipelines
 
..nehmen wir noch mal die Demostruktur:
Delphi-Quellcode:
Kunde1 
     Detail 1 
         Arbeit 1 
         Arbeit 2 
         Arbeit 3 
             Arbeitsbeschreibung 1 
                Beschreibungsdokument 1 
                Beschreibungsdokument 2 
     Detail 2 
         Arbeit 1 
         Arbeit 2 
     Detail 3 
     Detail 4 
         Arbeit 1 
             Arbeitsbeschreibung 1 
Kunde 2
wenn die Tabelle "Kunden" selectiert wird, wird anschließend die Tabelle "Detail" gefiltert (wegen afterScroll),
dadurch wird anschließend die Tabelle "Arbeit" gefiltert (wegen afterScroll),
dadurch wird anschließend die Tabelle "Arbeitsbeschreibung" gefiltert (wegen afterScroll),
dadurch wird anschließend die Tabelle "Beschreibungsdokument " gefiltert (wegen afterScroll),
u.s.w.
Wenn nun Arbeit 2 angesprungen wird, fängt die "afterScroll Sql-Aktion" ja wieder an..

Ich stell mir eher so was vor:
wenn die Tabelle "Kunden" selectiert wird,
wird anschließend jeder Eintrag von "Details" selektiert, der mit dem Kunden in Verbindung steht.
Anschließend wird jeder Eintrag von "Arbeit" selektiert, der mit dem Kunden in Verbindung steht.
Anschließend wird jeder Eintrag von "Arbeitsbeschreibung" selektiert, der mit dem Kunden in Verbindung steht.
Anschließend wird jeder Eintrag von "Beschreibungsdokument " selektiert, der mit dem Kunden in Verbindung steht.

und im afterScroll so was ähnliches wie:

Delphi-Quellcode:
ppBDEPipeline.ClearBookmarkList;
Tabelle first,
while not Tabelle.EOF do
begin
if Datensatz erfüllt Bedingung then setze Bookmark auf diesen..
Tabelle.next;
end;

Also wird einmal pro Tabelle ein SQL geschossen und der Client hat die gefilterte Datenmänge mal "vor sich"
via Bookmarks sag ich der Pipeline, welche Daten sie drucken soll..

wie könnte ich das "Bookmark setzen" für die Pipeline realisieren ?
Beispiel zur Frage:
Delphi-Quellcode:
Query1 = Select * from Tabelle
Datasource1 ist Verbunden mit Query1
ppDBPipeline1 ist verbunden mit Datasource1

ppBDEPipeline1.ClearBookmarkList
  Schleife durch das Query
    if Query1.fieldbyname('xy').asstring = 'yepp' then setze ein Bookmark für die Pipeline
  Schleife ende

nahpets 9. Sep 2009 16:24

Re: Optimieren der Datenbankabfragen für Reportpipelines
 
Hallo,
das von Dir gewünschte Verhalten erreichst Du doch mit table.Filter. Jede Tabelle bekommt in ihr AfterScroll das Setzen des Filter zur von ihr abhängigen Detailmenge.

Table1.Afterscroll setzt also den Filter für Table2, deren Afterscoll den Filter für Table3... .

Alle Tabellen (Querys) enthalten jedoch die gesamte Ergebnismenge analog zu select * from Tabelle, durch das Setzen der Filter im AfterScroll wird nur die für das Programm sichtbare Menge reduziert, beim Setzen von Table.Filtered := False ist sofort wieder die gesamte Datenmenge der Tabelle sichtbar.

SetRange verhält sich analog. Die Gesamtmenge der Daten muss daher nicht mehrfach von der Datenbank geliefert werden, ebensowenig ist ein Abholen der jeweils benötigten Teilmenge von der Datenbank erforderlich.

Mach Dir doch mal eine "Demo"-Applikation mit ein paar DBGrids für ein halbes dutzend Tabellen, wähle für alle Tabellen am Anfang die gesamte Datenmenge aus und setze in den jeweiligen AfterScroll-Ereignissen die Filter für die Detailtabellen. Nach dem Setzen der Filter auf Filtered := True ist eventuell noch ein First erforderlich, um das AfterScoll auszulösen.

Damit solltest Du Dir dann zumindest einen kleinen Überblick über das Laufzeitverhalten verschaffen können und sehen, ob die richtigen Teilmengen zusammengesucht werden.

erich.wanker 9. Sep 2009 16:53

Re: Optimieren der Datenbankabfragen für Reportpipelines
 
@nahpets

Hallo, vielen Dank für deine Hilfe.

Ich würd sehr ungern meine SQl-Querys gegen Table's austauschen.
Funktionieren tut das ganze ja - nur halt zu langsam ..

Ich denk, das grad die Query -SQLStatements (oder auch Table -Filter) die Hauptbremsen sind - weil si so oft vorkommen.

Die Tables würden mir ja die komplette Datenbank (alle Tabellen) auf den Client holen - (Performance vom Netz!) - vie SQL Statemnts hol ich mir wenigstens nur die "affected Rows" - nur halt zu oft ..

Erich

franktron 9. Sep 2009 17:00

Re: Optimieren der Datenbankabfragen für Reportpipelines
 
Also ich kenn Report Builder nicht aber in Fastreport geht das ganze so

Report

<masterdatail>Kunde1
<subdateil>Detail 1
. Arbeit 1
. Arbeit 2
. Arbeit 3
. Arbeitsbeschreibung 1
. Beschreibungsdokument 1
. Beschreibungsdokument 2
. Detail 2
. Arbeit 1
. Arbeit 2
. Detail 3
. Detail 4
. Arbeit 1
. Arbeitsbeschreibung 1
. Kunde 2

Die . sind für weiter Details

und dann im OnBeforePrint jeweils die Query Filtern (für jedes Detail eine eigene Query)

hoika 10. Sep 2009 07:21

Re: Optimieren der Datenbankabfragen für Reportpipelines
 
Hallo,

ich habe mir übrigens angewohnt,
jede Query durch den IBPlanalyzer zu jagen.
Der funktioniert bis auf einige Ausnahmen auch noch mit FB2.X.

Wie der Name sagt, analysiert er die Queries
und zeigt Probleme an.

Zur Not kann man auch IBExpert (Personal) dafür nehmen.
Dort wird der Plan aber nur als Text angezeigt.

Sobald aber irgendwo PLAN NATURAL steht
(also FullTable Scan), fehlt meistens ein Index.


Heiko


Alle Zeitangaben in WEZ +1. Es ist jetzt 09:09 Uhr.
Seite 1 von 2  1 2      

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