AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Datenbanken SQL Update-Befehl viel zu langsam
Thema durchsuchen
Ansicht
Themen-Optionen

SQL Update-Befehl viel zu langsam

Ein Thema von Perlsau · begonnen am 24. Dez 2013 · letzter Beitrag vom 24. Dez 2013
Antwort Antwort
Perlsau
(Gast)

n/a Beiträge
 
#1

SQL Update-Befehl viel zu langsam

  Alt 24. Dez 2013, 02:43
Datenbank: Firebird • Version: 2.5 • Zugriff über: IBDac
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:
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;
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:
Delphi-Quellcode:
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;
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?

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.

Crosspost im Delphi-Treff
  Mit Zitat antworten Zitat
HeZa

Registriert seit: 4. Nov 2004
Ort: Dortmund
182 Beiträge
 
Delphi 10 Seattle Professional
 
#2

AW: SQL Update-Befehl viel zu langsam

  Alt 24. Dez 2013, 07:42
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.
  Mit Zitat antworten Zitat
hstreicher

Registriert seit: 21. Nov 2009
220 Beiträge
 
Delphi 10.2 Tokyo Professional
 
#3

AW: SQL Update-Befehl viel zu langsam

  Alt 24. Dez 2013, 08:28
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
  Mit Zitat antworten Zitat
vagtler

Registriert seit: 9. Jul 2010
Ort: Köln
667 Beiträge
 
Delphi 2010 Professional
 
#4

AW: SQL Update-Befehl viel zu langsam

  Alt 24. Dez 2013, 09:07
Ich tippe auch auf einen Fehler auf Grund mangelnder SoC (http://en.wikipedia.org/wiki/Separation_of_concerns). Warum für Update kein ausschließlich dafür zuständiges Objekt (durchaus gerne mit begrenzter Lebenszeit) verwenden?
  Mit Zitat antworten Zitat
arnof

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

AW: SQL Update-Befehl viel zu langsam

  Alt 24. Dez 2013, 10:51
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:
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;
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:
Delphi-Quellcode:
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;
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?

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.

Crosspost im Delphi-Treff
Vorweg ich bin Interbase Laie, habe ich noch nie benutzt, aber folgendes generelles:

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:
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;
In diesem Sinne, ich hoffe es hilft und Frohe Weihnachten!
  Mit Zitat antworten Zitat
Perlsau
(Gast)

n/a Beiträge
 
#6

AW: SQL Update-Befehl viel zu langsam

  Alt 24. Dez 2013, 10:51
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:
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;
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
  Mit Zitat antworten Zitat
Perlsau
(Gast)

n/a Beiträge
 
#7

AW: SQL Update-Befehl viel zu langsam

  Alt 24. Dez 2013, 10:56
In diesem Sinne, ich hoffe es hilft und Frohe Weihnachten!
Danke, aber ich hatte die Zeit bereits direkt vor und direkt nach dem Execute gemessen, und das waren mal 3, mal 6, mal 12 bis zu über 20 Sekunden ... die anderen Zeiten hatte ich zuvor bereits gemessen und aufgrund des nicht weiter relevanten Zeitverbrauchs das Problem auf das Execute einschränken können. Natürlich wäre jetzt noch interessant herauszufinden, was denn diese Verzögerung eigentlich verursacht hat: Es gab zum Zeitpunkt der Execute-Ausführung weder irgendwelche Controls noch ausgelöste Ereignisse, die behandelt wurden, kein AfterScroll etc.
  Mit Zitat antworten Zitat
Benutzerbild von IBExpert
IBExpert

Registriert seit: 15. Mär 2005
672 Beiträge
 
FreePascal / Lazarus
 
#8

AW: SQL Update-Befehl viel zu langsam

  Alt 24. Dez 2013, 10:59
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
http://ibexpert.net/ibe/index.php?n=...0#DBMonitoring
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.
http://ibexpert.net/ibe/index.php?n=...#TraceAndAudit
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
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
Antwort Antwort


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 18:45 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