![]() |
AW: Optimierung Datenbankzugriff Firebird
Zitat:
in XE4 unit Data.SqlExpr, das sieht mir nicht besonders clever aus. Der rennt sogar zwei mal durch die Datenmenge, wenn beim ersten Durchlauf keine Übereinstimmmung gefunden wurde. Und diese Implementation ist leider nicht unüblich, auch wenn andere Komponenten das ggf irgendwie anders lösen, da sollte man sich aber nicht drauf verlassen.
Code:
"Das war zu Zeiten der BDE" ist da also doch nicht ganz zutreffend ...
First;
while not EOF do begin if CheckValues(AFields, Values, CaseInsensitive, PartialLength) then break; Next; end; { if not found, reset cursor to starting position } bFound := not EOF; if not bFound then begin First; while not EOF do begin if CheckValues(SaveFields, StartValues, False, False) then break; Next; end; end; Result := bFound; |
AW: Optimierung Datenbankzugriff Firebird
Ich befürchte, Du wirst nicht darum herum kommen, dich zu entscheiden: Entweder hohe Ladezeiten oder einen etwas anderen Aufbau deines UX: Wieso soll der Anwender durch 300.000 Datensätze scrollen dürfen? Wieso muss er nach der (z.B.) Schuhgröße oder anderen, vollkommen unwichtigen, Eigenschaften sortieren können? Kann man sein Anliegen nicht anders lösen? Wir haben z.B. einmal ein ähnliches Problem dadurch gelöst, in dem der Anwender genau befragt wurde, wieso er denn darauf besteht, 100.000 Datensätze im Grid zu sehen: Dabei hat sich dann herausgestellt, das er diese Daten filtert und exportiert, um sie in EXCEL weiter zu verarbeiten. Und dazu hat er die Daten sortiert und bestimmte Bereiche rausgeschnippelt.
Also haben wir ihm kurzerhand ein Export-Tool geschrieben, was nun viel schneller geht und sind erstens unser Problem los (wie sortiert man eine Tabelle mit 50 Spalten und > 1Mio Zeilen performant in der GUI?) und zweitens sein Problem: Die Anwendung lief nur noch auf den aktuellsten PC mit schneller CPU und viel RAM. Unser Exporttool läuft überall. Die UX haben wir dahingehend verändert, das er zur Darstellung seiner Daten immer einen Filter setzen muss, d.h. es werden nicht alle Daten angezeigt. Lässt er diesen leer, dann weiß er wenigstens, warum das jetzt so lange dauert. Ich kenne FB nicht so gut, aber i.a. sind Sortieroperationen auf indexierten Spalten wesentlich schneller als auf Spalten ohne Index. Ist auch irgendwie logisch. Ich glaube auch, das FB den Index nicht verwendet, wenn dieser z.B. aufsteigend sortiert ist, man selbst aber absteigend sortieren möchte. Du könntest allen Spalten deiner Tabelle nun einen Index spendieren, aber das wäre irgendwie bescheuert, denn nun hast Du bei der Datenänderung ein Performanceproblem, wenn es viele sind. Zudem kann man den Index nicht mehr so gut verwenden, wenn man nach mehreren Spalten sortieren will. [QUOTE=IBExpert;1214261] Zitat:
Allerdings ist hier ein wirklicher Lapsus: Beim zweiten Durchlauf sollte man aus der Schleife heraus, wenn man den ursprünglichen Record ein zweites Mal untersucht. Da man ab hier eh alles schon geprüft hat, kann man gleich ans Ende springen und die Schleife beenden. Also: Locate funktioniert, wenn es etwas zu finden gibt und ist dann lahm (ok, und nicht wirklich clever), wenn es nichts zu finden gibt. |
AW: Optimierung Datenbankzugriff Firebird
Zitat:
Delphi-Quellcode:
startet (Position an den Anfang des DataSets setzen).
First
Da ist also nix von ab hier. Und der zweite Suchlauf sucht einfach nur nach dem Datensatz, der aktiv war, bevor die Suche begann. Wenn dieser der letzte Datensatz im DataSet ist, dann wird die Datenmenge im WorstCase zweimal komplett durchsucht. |
AW: Optimierung Datenbankzugriff Firebird
Zitat:
Dann aber nicht beschweren, das das Schreiben extrem lahm wird. Bei 16k Pagesize gehen bis zu 818 single column indices pro Tabelle. Dann werden bei jedem Insert oder Update nicht nur die zugehörige Datenpage neu geschrieben, sondern auch noch mal bis zu 818 Indexpages. Denk noch mal über die Anregungen von Furtbichler nach. Es ist ganz selten sinnvoll, in einem Grid hundertausende Records ungefiltert anzuzeigen. Aber bitte dann nicht mit den Filtereigenschaften arbeiten, die sind häufig genau so blöde implementiert wie locate. Ohne kleine Datenmenge fliegt dir auch ab einer gewissen Datensatzanzahl die Funktionalität mit win32 schnell um die Ohren, dann startet dein Programm ab einer gewissen Datensatzanzahl gar nicht mehr, weil das Grid inkl Overhead bei so vielen Records auch schnell mal die 2GB Grenze sprengt. Zitat:
Aber wie du schon sagst, 2 komplette Durchläufe gibt es nur wenn es keine Übereinstimmung gibt und vorher der letzte aktiv war. Dafür muss ich aber nicht alle Daten zum Client schicken, dafür gibt es eigenständige SQL Befehle. Bei kleinen Datenmenge ist die Implementation in den Komponenten fast egal, aber 300000 Records sind schon mal per se keine kleine Datenmenge |
AW: Optimierung Datenbankzugriff Firebird
Ich kann Furtbichlers Maßnahmen nur unterstreichen.
Wir bauen Systeme, die so arbeiten: Verwendung z.B. ADO mit MAXRECORDS z.B. gleich 1000 Ableitung von TADOQuery/TADODataset wandelt Filter & Sort in Where-Bedingung/Order By um. Mehrere Millionen Datensätze Im Backend wird generell eine Dimension rausgefiltert, bleiben z.B. 200000 DS in großen Datenmengen Öffnen/Sortieren von komplexen Datenmengen dauert leider noch mehrere Sekunden Das ist natürlich nicht gewünscht, dafür gibt es spezialisierte Suchmasken mit einer handvoll Suchfeldern (indiziert) Öffnen der großen Datenmengen über PK Filter aus Suchmaske. Suchmasken und Ergebnisdarstellung liegen deutlich unter 0,5 Sekunden Der Kunde kann unabhängig davon auch die großen Datenmengen auf jedem Feld filtern oder sortieren. Wenn er schlau ist, filtert er erst nährungsweise im Sekundenbereich auf eine kleine, relevante(!) Menge, dann sortiert er im Millisekundenbereich. Auch ein Locate auf vorgefilteterten, kleinen Datenmengen läuft hinreichend schnell. |
Gesammelte Antworten
Zitat:
Zitat:
Zitat:
Zitat:
Zitat:
Achso, Frage: Was ist ein UX? User-Schnittstelle? |
AW: Gesammelte Antworten
Zitat:
Wirkt ein Index nicht, dann weil der Optimizer es nicht schnallt - oder der Entwickler-. Ein View ist nichts anderes als ein vorbereitetes Selectstatement. Du kannst es ja ausprobieren und die Zugriffszeiten testen. Die sollten gleich sein. (Ein View hat natürlich auch noch andere Zwecke, Interfaceschicht, Abstraktionsschicht, Berechtigungsschicht, ..), aber darum geht es hier ja gerade nicht. |
AW: Optimierung Datenbankzugriff Firebird
Zitat:
Zitat:
Zitat:
Column unknown BRASILIEN Die Procedure, die aufgerufen wird:
Delphi-Quellcode:
Wobei das Property FilterSQL laut Dokumentation nichts anderes macht als:
procedure TDatMod.SetFilter_OrteLand(Land: String);
begin View_Orte.FilterSQL := 'V_LAND=' + Land; end; // Example aus IbDac.pdf: // Query1.FilterSQL := 'Dept >= 20 and DName LIKE ''M%'''; Used to change the WHERE clause of SELECT statement and reopen a query. Übrigens derselbe Fehler, der auch beim Setzen der gewöhnlichen Filtereigenschaft auftritt, wie ich es zuerst versucht hatte:
Delphi-Quellcode:
Schon irgendwie seltsam ... vielleicht 'n Bug ...
procedure TDatMod.SetFilter_OrteLand(Land: String);
begin View_Orte.Filtered := False; View_Orte.Filter := 'V_LAND=' + Land; View_Orte.Filtered := True; end; |
AW: Optimierung Datenbankzugriff Firebird
Delphi-Quellcode:
View_Orte.FilterSQL := 'V_LAND=' + QuotedStr(Land);
|
AW: Optimierung Datenbankzugriff Firebird
nein, das ist korrekt:
Zitat:
Grüße |
Alle Zeitangaben in WEZ +1. Es ist jetzt 21:15 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz