AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Optimierung Datenbankzugriff Firebird

Ein Thema von Perlsau · begonnen am 5. Mai 2013 · letzter Beitrag vom 6. Mai 2013
Antwort Antwort
Seite 1 von 4  1 23     Letzte »    
Perlsau
(Gast)

n/a Beiträge
 
#1

Optimierung Datenbankzugriff Firebird

  Alt 5. Mai 2013, 01:53
Moin allerseits,

ich greife mit den IBDac-Komponenten auf eine Firebird-Datenbank zu, in der bereits 16 Tabellen existieren. Beim Verbinden mit den Tabellen vergehen knapp 8 Sekunden, und mir kommt das doch ein wenig lang vor. Zum Projekt:

Auf einem Datenmodul sitzen eine TIBCConnection, 16 TIBCTable mit den dazugehörenden TIBCDataSource und zwei TIBCTransaction. In OnShow der Hauptform rufe ich meine Verbindungs-Funktion auf:
Delphi-Quellcode:
function TDatMod.Verbinden_Datenbank : Boolean;
begin
   Trennen_Datenbank;

   ConMain.Username := Adr_Types.URec.DB_User;
   ConMain.Password := Adr_Types.URec.DB_Pass;
   ConMain.Options.Role := Adr_Types.URec.DB_Role;
   ConMain.Server := 'localhost';
   ConMain.SQLDialect := 3;
   ConMain.LoginPrompt := False;
   ConMain.Options.Charset := 'UTF8';
   ConMain.Options.UseUnicode := True;

   IF Adr_Types.DB_Embedded THEN
   BEGIN
        ConMain.ClientLibrary := Adr_Types.URec.Pfad_Main + Adr_Types.Client_EmbedDLL;
        ConMain.Database := Adr_Types.URec.Pfad_Main + Adr_Types.DatenbankDateiName;
   END ELSE
   BEGIN
        ConMain.ClientLibrary := Adr_Types.URec.Pfad_Main + Adr_Types.Client_ServerDLL;
        ConMain.Database := Adr_Types.URec.Pfad_DB + Adr_Types.DatenbankDateiName;
   END;

   TRY
      ConMain.Connect;
   EXCEPT
      on e:exception DO ShowMessage('Fehler beim Verbinden mit der Datenbank: ' + e.Message);
   END;

   Result := ConMain.Connected;
end;
Das dauert meinen Messungen nach in der IDE im Debug-Mode 141 Millisekunden, dagegen als Exe Release gestartet nur noch 93 ms. Der Verbindungsaufbau zur Datenbank ist also nicht das Problem, wie ich oben schon andeutete. Die 16 TIBCTable-Komponenten auf Active := True zu setzen, dauert:
IDE Debug-Mode 8827 ms,
Exe Release 7155 ms.

Danach kommt das Setzen diverser Einstellungen von Tabellen, Sortierreihenfolgen usw., das dauert:
IDE Debug-Mode 2422 ms,
Exe Release 1828 ms.

Die Tabellen setze ich mit TIBCTable.Open aktiv:
Delphi-Quellcode:
function TDatMod.Verbinden_Tabellen: Boolean;
begin
     Result := False;

     TRY
        Tab_Benutzer.Open;
        Tab_Rechte.Open;
        Tab_Geschlecht.Open;

        ...

        Result := True;
     EXCEPT
        on e:exception DO ShowMessage('Fehler beim Verbinden mit den Tabellen: ' + e.Message);

     END;
end;
Von einem freundlichen Programmiererkollegen mit Win 7 und Radstudio XE2 erhielt ich folgende Testergebnisse, nachdem er mein Projekt auf seinem System getestet hatte:

*** Wie oben Win 7 32 Bit Debug
IF NOT DatMod.Verbinden_Datenbank THEN 70
IF NOT DatMod.Verbinden_Tabellen THEN 5129
Set_Einstellungen; 2327

*** Wie oben Win 7 64 Bit Debug
IF NOT DatMod.Verbinden_Datenbank THEN 58
IF NOT DatMod.Verbinden_Tabellen THEN 3867
Set_Einstellungen; 1847

*** Wie oben Win 7 32 Bit Release
IF NOT DatMod.Verbinden_Datenbank THEN 60
IF NOT DatMod.Verbinden_Tabellen THEN 5076
Set_Einstellungen; 2306

*** Wie oben Win 7 64 Bit Release
IF NOT DatMod.Verbinden_Datenbank THEN 64
IF NOT DatMod.Verbinden_Tabellen THEN 3855
Set_Einstellungen; 1777

*** Wie oben Win 7 32 Bit Debug IDE
IF NOT DatMod.Verbinden_Datenbank THEN 160
IF NOT DatMod.Verbinden_Tabellen THEN 5957
Set_Einstellungen; 2532
DatMod.ZweiteVerbindung; 55

*** Wie oben Win 7 64 Bit Release
IF NOT DatMod.Verbinden_Datenbank THEN 196
IF NOT DatMod.Verbinden_Tabellen THEN 3854
Set_Einstellungen; 1579
DatMod.ZweiteVerbindung; 48


Auf seinem Rechner, der ungefähr dieselbe Taktfrequenz und Ausstattung wie meiner hat (2x3 GHz, 4 GB Speicher) geht es also am schnellsten, wenn er eine 64-Bit-Anwendung erzeugt und mit einer 64-Bit-Firebird-Installation arbeitet. Leider kann ich nur 32-Bit-Anwendungen erzeugen, aber ich glaube, daß man das irgendwie optimieren kann, hab aber im Moment keinen blassen Schimmer, wo ich ansetzen könnte.

Der Eintrag DatMod.ZweiteVerbindung; in den letzten beiden Versuchen beschreibt die Zeit, die eine zweite Verbindung mit nur einer Tabelle benötigt (incl. Datenbankverbindung und Tabellen-Komponente auf aktiv setzen. Bei dieser zweiten Verbindung wurden keine Komponenten aufs Datenmodul geschoben, sondern dieselben im Create des Datenmoduls erst erzeugt:
Delphi-Quellcode:
procedure TDatMod.DataModuleCreate(Sender: TObject);
begin
   ConMainX := TIBCConnection.Create(DatMod);
   TransMainX := TIBCTransaction.Create(DatMod);
   Tab_LandX := TIBCTable.Create(DatMod);
   Dsrc_LandX := TIBCDataSource.Create(DatMod);
end;
Die Verbindung wird bei dieser Zweitverbindung erst hergestellt, wenn die erste Verbindung bereits besteht:
Delphi-Quellcode:
procedure TDatMod.ZweiteVerbindung;
begin
     ConMainX.Username := Adr_Types.URec.DB_User;
     ConMainX.Password := Adr_Types.URec.DB_Pass;
     ConMainX.Options.Role := Adr_Types.URec.DB_Role;
     ConMainX.Server := 'localhost';
     ConMainX.SQLDialect := 3;
     ConMainX.LoginPrompt := False;
     ConMainX.Options.Charset := 'UTF8';
     ConMainX.Options.UseUnicode := True;
     ConMainX.ClientLibrary := Adr_Types.URec.Pfad_Main + Adr_Types.Client_ServerDLL;
     ConMainX.Database := Adr_Types.URec.Pfad_DB + Adr_Types.DatenbankDateiName;
     ConMainX.DefaultTransaction := TransMainX;
     ConMainX.Connect;
     TransMainX.Active := True;
     Tab_LandX.Connection := ConMainX;
     Tab_LandX.TableName := 'LAND';
     Tab_LandX.KeyGenerator := 'GEN_LAND_ID';
     Tab_LandX.KeyFields := 'IDX_LAND';
     Tab_LandX.IndexFieldNames := '';
     Tab_LandX.Options.BooleanDomainFields := True;
     Tab_LandX.Open;
     Dsrc_LandX.DataSet := Tab_LandX;
     Dsrc_LandX.Enabled := True;
end;
Wäre es angesichts der Tatsache, daß die Zweitverbindung nur 48 ms inkl. einer Tabelle benötigt, hilfreich, alle Komponenten erst zur Laufzeit zu erzeugen? Ich könnte das ja mühevoll austesten, aber vielleicht hat ja bereits jemand diesen Versuch gemacht.

Was gäbe es sonst noch für Möglichkeiten, die Herstellung der Verbindungen zu beschleunigen?
  Mit Zitat antworten Zitat
Benutzerbild von haentschman
haentschman

Registriert seit: 24. Okt 2006
Ort: Seifhennersdorf / Sachsen
5.388 Beiträge
 
Delphi 12 Athens
 
#2

AW: Optimierung Datenbankzugriff Firebird

  Alt 5. Mai 2013, 09:18
Moin...

die Lösung ist einfach...
Zitat:
Die 16 TIBCTable-Komponenten auf Active := True zu setzen, dauert:
...Queries benutzen und nur die Daten holen die wirklich benötigt werden. Sollte dann die Datenmenge immer noch zu groß sein bleibt nur ein Fortschrittsbalken oder ein Design überdenken
  Mit Zitat antworten Zitat
mkinzler
(Moderator)

Registriert seit: 9. Dez 2005
Ort: Heilbronn
39.861 Beiträge
 
Delphi 11 Alexandria
 
#3

AW: Optimierung Datenbankzugriff Firebird

  Alt 5. Mai 2013, 09:26
Ich vermute auch, dass es an den beim Öffnen zu ladenenden Datenmengen liegt. Ich bezweifle, dass alle 16 sofort benötigt werden und, wie haentschman schon schrieb, die bei den benötigten Tabellen nicht deren vollständigen Inhalt.

Zudem kannst du auch mit der embedded Dll auf einen Server zugreifen ( dann über IP)
Markus Kinzler
  Mit Zitat antworten Zitat
Benutzerbild von IBExpert
IBExpert

Registriert seit: 15. Mär 2005
680 Beiträge
 
FreePascal / Lazarus
 
#4

AW: Optimierung Datenbankzugriff Firebird

  Alt 5. Mai 2013, 09:29
Moin,

das hängt von verschiedenen Faktoren ab, u.a. deinem Tabellendesign, aber auch generell davon, das du halt TTable Varianten benutzt. Da sind längst nicht alle Komponentenvarianten schnell und die treiben meistens einen Riesen Overhead gegenüber reinen SQL Komponenten, bei denen du bestimmt, welches SQL ausgeführt wird und wann es ausgeführt wird. Wenn du sehr viele Felder in deinen Tabellen hast müssen wesentlich mehr Metadaten geladen werden.

Was Firebird wirklich macht kannnst du z.B. bei FB25 mit der TraceAPI erkennen
http://ibexpert.net/ibe/index.php?n=Doc.TraceAndAudit (geht auch mit der IBExpert Trial, aber nicht mit der Personal, gibt aber auch andere Tools)

Dazu kommt dann noch die von dir benutzte Firebird Version. Wenn es der Superclassic oder classic ist und du anden Cache Buffers nichts geändert hast, dann liegt wohl auch da der Hund begraben. Beim Superserver, den ich für jeden empfehle, der sich weniger mit FB auskennt, der default cache buffer mit 2048 ok, beim classic oder superclassic mit 75 viel zu gering. sehe kannst du den Wert in der Datenbankstatistik oder hier
http://ibexpert.net/ibe/index.php?n=...baseProperties (da kannst du den wert auch höher setzen, Mindestwert 2000, besser 10000).

Ich hab mir die statischen Datenmodule mit hunderten von Komponenten schon vor Jahren abgewöhnt. Bei diversen Delphi Consulting Jobs sehe ich aber noch Datenmodule mit hunderten von Datasets, das ist kaum wartbar, entsteht aber meistens im Laufe der Jahre weil man mal so angefangen hat und nun an zig tausend TField Objekten und TDataset Events was rangebastelt hat, was man nicht mal eben ändern kann. Ich erzeuge alle Datasets zur Laufzeit, aber performancemäßig macht das eigentlich keine Unterschied.

Wenn es geht, dann vermeide generell TTable Varianten, da geht Komfort für den Programmierer zu Lasten Performance für Endanwender.

Evtl. hast du aus der TraceAPI ode rdurch geänderte Cache Buffers ja schon neue Erkenntnisse
Holger Klemt
www.ibexpert.com - IBExpert GmbH
Oldenburger Str 233 - 26203 Wardenburg - Germany
IBExpert and Firebird Power Workshops jederzeit auch als Firmenschulung
  Mit Zitat antworten Zitat
arnof

Registriert seit: 25. Apr 2013
1.254 Beiträge
 
Delphi 10.1 Berlin Enterprise
 
#5

AW: Optimierung Datenbankzugriff Firebird

  Alt 5. Mai 2013, 11:03
Moin...

die Lösung ist einfach...
Zitat:
Die 16 TIBCTable-Komponenten auf Active := True zu setzen, dauert:
...Queries benutzen und nur die Daten holen die wirklich benötigt werden. Sollte dann die Datenmenge immer noch zu groß sein bleibt nur ein Fortschrittsbalken oder ein Design überdenken
wir er schon ngeschrieben hat, mit tables auf active = True, läds Du alle Datenbank inhalte in deinen RAM, das wird immer länger dauern, je mehr Daten Du in der DB hast.....

Schau Dir auch mal im Taskmanager den Ramverbrauch deiner EXE an, da wirst Du sehen je mehr Daten da sind desdo mehr ram verbraucht deine exe.

PS: bei 2 GB ist dann schluß .. bei 32 bit anwendung ....
  Mit Zitat antworten Zitat
Benutzerbild von IBExpert
IBExpert

Registriert seit: 15. Mär 2005
680 Beiträge
 
FreePascal / Lazarus
 
#6

AW: Optimierung Datenbankzugriff Firebird

  Alt 5. Mai 2013, 11:32
wir er schon ngeschrieben hat, mit tables auf active = True, läds Du alle Datenbank inhalte in deinen RAM, das wird immer länger dauern, je mehr Daten Du in der DB hast.....
wenn deine TTable Komponente das macht, dann schmeiss die weg, das passiert zwar gerne mal bei clientdatasets oder memorydatasets oder wenn man sinnloserweise einfach mal recordcount abfragt, aber durch active=true auf sinnvoll prgrammierten ttable varianten ist das nicht der Fall.
Holger Klemt
www.ibexpert.com - IBExpert GmbH
Oldenburger Str 233 - 26203 Wardenburg - Germany
IBExpert and Firebird Power Workshops jederzeit auch als Firmenschulung
  Mit Zitat antworten Zitat
Perlsau
(Gast)

n/a Beiträge
 
#7

AW: Optimierung Datenbankzugriff Firebird

  Alt 5. Mai 2013, 13:07
@alle: Das sind in er Tat sehr nützliche Tipps und Hinweise, die ihr da parat habt. Es wird echt Zeit, daß ich mich mit all diesen Optimierungsmöglichkeiten eingehender befasse. Immerhin hab ich heute nacht noch bis gegen 4 Uhr herumprobiert und getestet. Ich hab da eine Tabelle, die enthält 10 Felder und derzeit ca. 300.000 Datensätze. Bin noch am Einlesen, am Ende werden es knapp eine Million Datensätze sein, dazu 5 Untertabellen mit jeweils 2 bis 4 Feldern, die auch bis zu 50.000 Datensätze fassen.

Auf die meisten Tabellen werden beim Start Locate-Methoden angewandt, um die zuletzt bearbeiteten Datensätze für den Anwender sofort sichtbar zu machen. Auch das werde ich nochmal überdenken, denn eigentlich benötigt der Anwender nur zwei oder drei Tabellen, mit denen er wirklich ständig arbeitet. Das sollte auch etwas Geschindigkeit beim Start bringen.

In den Options der Tab-Kompos habe ich bereits das Property QueryRecordCount deaktiviert. Das hat die Sache schon mal ein wenig beschleunigt, denn das Durchzählen der Datensätze nimmt natürlich auch Zeit in Anspruch. Ich werde den RecordCount bei den entsprechenden Tabellen in der Anwendung verwalten.

@Holger Klemt & haentschman: Die Table-Komponente von IBdac soll ja laut Dokumentation ein direkter Abkömmling von TCustomIBCQuery sein. Aber ich probier's heute mal aus, problematische Table-Komponenten durch Queries zu ersetzen. Bei den Tabellen für Benutzereinstellungen, Benutzerrechte, Geschlecht und Anrede kann ich mir das schenken, die enthalten nur ein paar Datensätze.

@Holger Klemt: Hab leider nur die Personal-Version von IBExpert. Aber die Database-Properties kann ich mir natürlich anzeigen lassen: Unter Buffer steht Pages auf 90 und KB auf 1440. Hab jetzt mal den Wert auf 10000 kb erhöht, dabei entstehen 625 Seiten und der Sweep-Interval steht auf 20000.

Leider weiß ich nicht mehr genau, welche Firebird-Version (v2.5) ich installiert hatte, aber ich glaube mich zu erinnern, daß es er Classic-Server war. IBexpert schreibt mir das heraus, wenn ich die Servereigenschaften abfrage:
Server Version: WI-V2.5.2.26539 Firebird 2.5
Server Implementation: Firebird/x86/Windows NT
Service Version: 2

Ich vermute auch, dass es an den beim Öffnen zu ladenenden Datenmengen liegt. Ich bezweifle, dass alle 16 sofort benötigt werden und, wie haentschman schon schrieb, die bei den benötigten Tabellen nicht deren vollständigen Inhalt.
Ich glaube nicht, daß TIBCTable die gesamte Datenmenge in den Speicher lädt. Aber die Tabellen werden schon benötigt, weil sie Untertabellen für die noch fehlende Haupttabelle darstellen, die hauptsächlich aus Feldern der Untertabellen zusammengesetzt sein wird.

Zudem kannst du auch mit der embedded Dll auf einen Server zugreifen ( dann über IP)
Die Embedded.dll ist aber wesentlich größer als die "normale": 3.801.088 vs 552.960 Bytes. Das muß meiner Ansicht nach nicht sein, für den Zugriff auf den lokalen Firebird-Server die knapp 4 MB große DLL einzusetzen. Diese ist nur dafür gedacht, daß de Anwender sein Programm von einem externen Datenträger, z.B. einem Stick oder einer externen Festplatte, starten möchte. Der Anwender soll in die Lage versetzt werden, bei Bedarf Datenbank und Anwendung zu kopieren und "mitzunehmen".

@alle: Nochmal vielen Dank an euch, ich werde jetzt gleich nach dem verspäteten Frühstück darangehen, eure Vorschläge umzusetzen.
  Mit Zitat antworten Zitat
jobo

Registriert seit: 29. Nov 2010
3.072 Beiträge
 
Delphi 2010 Enterprise
 
#8

AW: Optimierung Datenbankzugriff Firebird

  Alt 5. Mai 2013, 13:48
Meine Empfehlung wären ebenfalls Queries, die gezielt Teilmengen abrufen.
Mit Table Komponenten habe ich schon lange nicht mehr gearbeiet, gibt es da sowas wie max-records?
Wenn Du bei Tables bleiben musst/willst, probier doch mal Filter auf PK Felder, die garantiert eine leere Menge ergibt (oder eine garantiert kleine~1 Datensatz z.B...
Im weiteren Programmverlauf muss natürlich was sinnvolles in den Filter rein, Hauptsache, die große Tabellen werden nicht/niemals ungefiltert geöffnet und alles wird geladen.
Gruß, Jo
  Mit Zitat antworten Zitat
Benutzerbild von sx2008
sx2008

Registriert seit: 16. Feb 2008
Ort: Baden-Württemberg
2.332 Beiträge
 
Delphi 2007 Professional
 
#9

AW: Optimierung Datenbankzugriff Firebird

  Alt 5. Mai 2013, 14:06
Ich hab mir die statischen Datenmodule mit hunderten von Komponenten schon vor Jahren abgewöhnt. ... das ist kaum wartbar...
Ich erzeuge alle Datasets zur Laufzeit, aber performancemäßig macht das eigentlich keine Unterschied.
Statische (Query-)Komponenten aus Datenmodulen sind schon in Ordnung solange man es mit der Stückzahl nicht übertreibt.
Die Obergrenze liegt so bei 16 bis 20 Stück.
Es ist wichtig, die Abfragen thematisch auf mehrere Datenmodule zu verteilen und jedes Datenmodul möglichst so zu designen, dass es keine Abhängigkeiten zu anderen Datenmodulen hat.

Du hast ganz richtig erkannt, dass zu viele Datasets auf einem Datenmodul extrem schwer zu warten sind.
Deine Schlussfolgerung in Zukunft ALLE Datasets zur Laufzeit zu erzeugen ist aber auch nicht die Lösung.
Du verschenkst damit Entwicklungszeit und erhöhst die Menge des Sourcecodes.
(je mehr Sourcecode, umso mehr Fehlermöglichkeiten gibt es)
  Mit Zitat antworten Zitat
Perlsau
(Gast)

n/a Beiträge
 
#10

AW: Optimierung Datenbankzugriff Firebird

  Alt 5. Mai 2013, 14:11
Meine Empfehlung wären ebenfalls Queries, die gezielt Teilmengen abrufen.
Mit Table Komponenten habe ich schon lange nicht mehr gearbeiet, gibt es da sowas wie max-records?
Wenn Du bei Tables bleiben musst/willst, probier doch mal Filter auf PK Felder, die garantiert eine leere Menge ergibt (oder eine garantiert kleine~1 Datensatz z.B...
Im weiteren Programmverlauf muss natürlich was sinnvolles in den Filter rein, Hauptsache, die große Tabellen werden nicht/niemals ungefiltert geöffnet und alles wird geladen.
Ebenso wie TIBCTable fragt TIBCQuery nur die Anzahl an Zeilen aus der zugrundeliegenden DB-Tabelle ab, die im Property FetchRows angegeben ist, das bei mir defaultmäßig auf 25 steht. Nur bei Abfrage von RecordCount, dem Setzen des Properties FetchAll oder/und dem Setzen des Properties QueryRecCount werden alle Datensätze abgefragt, aber außer bei FetchAll nicht im Speicher behalten. Diese drei Properties stehen bei mir alle auf False.

Mit dem Umstellen von TIBCTable auf TIBCQuery habe ich das goldene Los gezogen, die Startzeit hat sich nun merklich verringert:
Code:
IF NOT DatMod.Verbinden_Datenbank THEN   124
IF NOT DatMod.Verbinden_Tabellen THEN     31
Set_Einstellungen;                      2156

Geändert von Perlsau ( 5. Mai 2013 um 14:15 Uhr)
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 4  1 23     Letzte »    


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 21:20 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