![]() |
Datenbank: Firebird • Version: 2.5 • Zugriff über: IBDac
SQL Update-Befehl viel zu langsam
Moin allerseits,
in einer Firebird-Tabelle befinden sich rund 24.000 Einträge, die ich in einem VirtualTreeview anzeige. Die Tabellen-Spalte MARKIERT nimmt einen Boolean-Wert auf, der den Checkbox-Status repräsentiert. Wenn ich nun im VirtualTreeView alle Einträge markieren möchte (= in allen Checkboxen den Haken setzen), verwende ich diesen SQL-Befehl via SQL-Komponente:
Delphi-Quellcode:
Danach wird VirtualTree neu eingelesen. Das Problem: Wenn ich diesen SQL-Befehl im DB-Manager (IBExpert) eingebe, dauert die Ausführung incl. Commit und Refresh der Anzeige ca. 5 Sekunden. Mache ich das via Delphi, dann vergehen zwischen 17 und 21 Sekunden, wobei das Anzeigen im TreeView weniger als 1 Sekunde benötigt. Seltsamerweise geht das bedingte Update (Toggle) des Feldes ein wenig schneller: zwischen 13 und 16 Sekunden:
Procedure TDatBankEdit.Vst_MarkAll;
begin DatMod.Dsrc_Berufe.Enabled := False; DatMod.SQLMain.SQL.Text := 'update BERUFE set MARKIERT = 1'; DatMod.SQLMain.Execute; DatMod.Qset_Berufe.Refresh; end;
Delphi-Quellcode:
In IBExpert dauert das dagegen auch nur ca. 5 Sekunden. Was kann ich tun, damit ich annähernd die Geschwindigkeit erreiche, die IBExpert drauf hat?
Procedure TDatBankEdit.Vst_MarkToggle;
begin DatMod.Dsrc_Berufe.Enabled := False; DatMod.SQLMain.SQL.Text := 'update BERUFE set MARKIERT = iif((MARKIERT = 0),1,0)'; DatMod.SQLMain.Execute; DatMod.Qset_Berufe.Refresh; end; Bevor sich jemand wundert: Der Checkbox-Status wird natürlich deshalb in der DB gespeichert, damit der Anwender das beim nächsten Start wieder zur Verfügung hat. Beim Ändern einzelner Checkboxen im VirtualTree wird natürlich nur der entsprechende Eintrag in der DB aktualisiert und nicht jedesmal alles. Es gibt aber Buttons bzw. Menüeinträge, mit denen man alle, keine oder invertiert markieren kann. Die Markierungen dienen der späteren Auswahl beim Drucken, Exportieren usw. ![]() |
AW: SQL Update-Befehl viel zu langsam
Du hast recht, dass ist erstmal nicht zu verstehen. Eigentlich ist das für mich nur durch das Neuladen des Treeviews zu erklären, aber das hast du ja bereits ausgeschlossen.
Falls du also schon die Zeit von vor dem Execute bis genau nach dem Execute (Ohne dem Refresh) gemessen hast, würde ich das ganze mit einem Testprojekt ohne Treeview, das nur das UPDATE absetzt ausprobieren. Ist der Zeitunterschied dann immer noch so groß, hätte ich die Zugriffskomponenten in Verdacht. Um das Problem ganz anders zulösen (und auch viel schneller), kannst du ein neue Tabelle anlegen die immer genau einen Satz mit nur einem Feld "markiert" enthält, das drei Werte annehmen kann, nämlich nichts markiert (0), alles markiert (1), individuell (2). Beim SELECT joinst du die beiden Tabellen SELECT <andere felder von Berufe>, IIF((bss.markiert = 2), b.markiert, bss.markiert) AS markiert FROM berufe b, berufeselektionsstatus bss Beim klicken von "alles markiert" oder "nichts markiert" machst du nur das UPDATE auf berufselektionsstaus. Beim klicken der einer einzelnen Checkbox, machst du dein bisheriges UPDATE plus ein UPDATE auf berufselektionsstaus mit "markiert = 2". Ciao Heinz Z. |
AW: SQL Update-Befehl viel zu langsam
Viele Fragen :
- SQLMain , was sind für Komponenten - Transactions Settings - hängt evtl ein Datasource dran das irgendwas updatet ? - OnChange , Onscroll oder sowas Events ? dass das bedingte Update schnell geht wäre ein Hinweis auf den 3 oder 4 Punkt mfg Hannes |
AW: SQL Update-Befehl viel zu langsam
Ich tippe auch auf einen Fehler auf Grund mangelnder SoC (
![]() |
AW: SQL Update-Befehl viel zu langsam
Zitat:
Um dein Problem zu finden musst Du einfach mal die Zeiten Stoppen und Dir ausgeben lassen, ich würde behaupten, der Update sollte zwischen allen Programmen und der gleichen Datenbank gleich schnell sein (den mach ja die Datenbank selbst). Das Problem wird dein Refresh machen:
Delphi-Quellcode:
In diesem Sinne, ich hoffe es hilft und Frohe Weihnachten!:xmas:
Procedure TDatBankEdit.Vst_MarkToggle;
var t1,t2,t3,t4,t5:TTime; begin t1:=now; DatMod.Dsrc_Berufe.Enabled := False; DatMod.SQLMain.SQL.Text := 'update BERUFE set MARKIERT = iif((MARKIERT = 0),1,0)'; t2:=now; DatMod.SQLMain.Execute; t3:=now; DatMod.Qset_Berufe.Refresh; t4:=now; Memo1.Lines.Text:='Zeit 1 :'+TimeToStr(t2-t1); Memo1.Lines.Add('Zeit 2 :'+TimeToStr(t3-t1)); Memo1.Lines.Add('Zeit 3 :'+TimeToStr(t4-t1)); end; |
AW: SQL Update-Befehl viel zu langsam
Manchmal hilft es, einfach nur ein paar Hinweise aus anderen Köpfen zu lesen, um die eigenen Denkprozesse aus der Sackgasse zu führen. Dank eurer Antworten bin ich auf eine ganz einfache Lösung gestoßen: Stored Procedures in der DB anlegen und die bei Bedarf aufrufen:
Delphi-Quellcode:
Dabei werden meine knapp 24.000 Einträge in 0,8 bis 0,9 Sekunden aktualisiert. Somit sei euch allen, die ihr meine grauen Zellen erfolgreich angeregt habt, herzlich gedankt :thumb:
Procedure TDatBankEdit.Vst_Mark(Modus: Byte);
begin DatMod.Dsrc_Berufe.Enabled := False; CASE Modus OF 0 : DatMod.StoredProcMain.StoredProcName := 'BERUFE_MARKNONE'; 1 : DatMod.StoredProcMain.StoredProcName := 'BERUFE_MARKALL'; 2 : DatMod.StoredProcMain.StoredProcName := 'BERUFE_MARKTOGGLE'; END; DatMod.Trans_Main.Active := True; DatMod.Trans_Update.Active := TRue; DatMod.StoredProcMain.ExecProc; DatMod.Qset_Berufe.Refresh; end; |
AW: SQL Update-Befehl viel zu langsam
Zitat:
|
AW: SQL Update-Befehl viel zu langsam
Ich finde generell ein Update auf 24000 Datensätzen in 5 Sekunden relativ lahm, kann aber an deiner Tabellenstruktur liegen oder
an der verwendeten Festplatte (bei SSDs sollte das schneller sein) oder auch an denr Firebird Version bzw Parametern wie cache Buffers usw. Falls Trigger auf der Tabelle sind, dann würden die ja ggf auch ausgeführt werden. Ich habe gerade mal einen Test auf einer lokalen DB gemacht und bin dabei (mit SSD) auf 25000 Updates in 0,75 Sekunden gekommen. Mir kam dabei aber noch folgende Idee: Flüchtige Daten wie die Markierungen sind ausgeprochen unsinnig in der Tabelle selbst gespeichert, weil du damit schon mal keine netzwerkfähigkeit hast. Wie wäre eine extra Tabelle, die nur die Primärschlüssel deiner Tabelle speichert, die ausgewählt sind (optional mit User, der markiert, und schon wäre das netzwerkfähig). Für das Füllen des Treeview verbindest du deine Daten per left outer join mit den Markierungen. Wenn 100 Datensätze markiert sind, hast du bei meinem Verfahren 100 Datensätzen mit pk in einer extra Tabelle, die vieleicht gerade mal eine Datenpage belegt. Bei deinem Verfahren hast du 23900 mal den Feldwert 0 und 100 mal den Feldwert 1, verteilt auf sämtliche Datenpages. Bei Update (insbesondere alle Markierungen löschen) werden dann nämlich bei deinem Verfahren sämtliche Datenpages verändert, bei meinem Verfahren gibt es nur ein paar Deletes in wenigen Datenpages. Wenn es aber generell um die Erkenntnis geht, was da den Geschwindigkeitsunterschied auf Seite von Firebird ausmacht, dann: wenn du die ibexpert vollversion hast, dann steht dir in Services-Database Monitor eine Liste der ausgeführten SQLs zur Verfügung ![]() Mit der Personal Edition musst du dir das händisch aus der MON$STATEMENT zusammensuchen Da wird es sicherlich schon einige Unterschiede geben, Delphi Komponenten machen gerne mal viel unsinnigen Overhead. Noch detaillierter liefert dir die TraceAPI dazu Ergebnisse, weil darin alle Befehle protokolliert werden, auch ausgeführte Trigger etc. ![]() Bei der Personal Edition fehlt das, aber die Firebird Kommandozeilentools könnte man auch benutzen. p.s.: Wer umsteigen will von der Personal Edition: Einfach mal den Code DPSPECIAL im IBExpert Shop ausprobieren ;-) Ich geh erfahrungsgemäß davon aus, das die Geschwindigekeitsunterschiede durch Delphi Kompnenten versursacht werden, das kannst du normalerweise mit der traceapi oder im sql monitor sehr schnell finden |
Alle Zeitangaben in WEZ +1. Es ist jetzt 16:32 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