Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Datenbanken (https://www.delphipraxis.net/15-datenbanken/)
-   -   Delphi Updates mit Zeos/MySQL dauert zu lange? (https://www.delphipraxis.net/82315-updates-mit-zeos-mysql-dauert-zu-lange.html)

dbdeath74 11. Dez 2006 09:38

Datenbank: MySQL • Version: 5 • Zugriff über: Zeos 6.6.0

Updates mit Zeos/MySQL dauert zu lange?
 
Hallo,

ich hänge gerade eine Applikation von MSSQL Server auf mySQL um.
Nun dauert etwas was mit MSSQL 1s dauert auf einmal 6s :(

Etwas langsamer sehe ich ja ein, aber Faktor 6? Kann das sein?

Es sind folgende Updates, die Pro Gerät ca 100mal ausgeführt werden.
Wie ich herausgefunden habe ist es der Update Befehl der so lange brauch.
Die Operationen auf dem lokalen Dataset habe ich ja bei MSSQL auch, das sollte nicht der Faktor sein.

Ich gehe auf den Primary Key der Tabelle, der indiziert ist.
Irgendjemand eine Idee wie man das verbessern könnte?

Delphi-Quellcode:
    // wenn Update eines Gerätes dann prüfe ob Software schon vorhanden
            If DSSoftwareGeraet.DataSet.Locate('SoftwareID; VersionID',VarArrayOf([
              intToStr(SoftwareID) ,IntToStr(VersionID)]),[loCaseInsensitive]) then
            begin
              // Falls ja aktualisiere LastScan Datum
              ScanID := DSSoftwareGeraet.DataSet.FieldByName('ID').AsInteger;
              Close;
              SQL.Clear;
              SQL.Add('UPDATE CMDB_Software_Scan SET LastScan ='+QuotedStr(DateTimeToStr(scanDate)));
              SQL.Add(', Aktiv = 1');
              SQL.Add(' WHERE ID = '+IntToStr(ScanID));
              ExecSQL;
            end;
Gruß Oliver

Bernhard Geyer 11. Dez 2006 09:50

Re: Updates mit Zeos/MySQL dauert zu lange?
 
Wie groß ist die Tabelle CMDB_Software_Scan?
MySQL ist bei der Installation sehr zurückhaltend was den maximal verwendeten Hauptspeicher angeht im Gegensatz zu anderen DBMS die bei Bedarf oder auch sofort allen möglichen Speicher sich reservieren.

dbdeath74 11. Dez 2006 09:55

Re: Updates mit Zeos/MySQL dauert zu lange?
 
Hallo,

momentan sind es erst 2500 Datensätze, da ich noch in der Testphase bin.
Im Betrieb werden es wohl maximal 50-100k Datensätze werden.

Was mir aber gerade noch aufgefallen ist, ein Insert dauert genausolange oO

Also wenn ich statt 100 updates auf die Tabelle 100 Inserts mache.
Das macht für mich jetzt gar keinen Sinn mehr :(

Ein INSERT sollte doch viel schneller gehen oder?

Ich hatte es am Anfang auch erst mit mySQL-Connector ODBC Treibern und ADO Komponenten versucht, das war auch so lahm.
Deswegen bin ich auf Zeos gegangen, mit der Hoffnung das es damit schneller ist als über den riesigen ODBC Umweg.

Aber leider Fehlanzeige :(

Gruß Oliver

Bernhard Geyer 11. Dez 2006 10:01

Re: Updates mit Zeos/MySQL dauert zu lange?
 
Was passiert wenn Du z.B. mit dem MySQL Query Browser das Statement direkt absetzt.
Wir unterstützen selbst MySQL und MS-SQL und haben bei "normalen" DB-Größen keine großartigen Geschwindigkeitsunterschiede festgestellt. Und ZEOS sollte auch nicht mehr so langsam sein.

hoika 11. Dez 2006 10:08

Re: Updates mit Zeos/MySQL dauert zu lange?
 
Hallo,

ich denke nicht dass das Update das Problem ist,
sondern das Locate (oder fehlender Index).
Eretze das doch mal durch
"Select ScanId From Where SoftwareID=:SoftwareID and VersionID=:VersionID"

Optimale Performance erhälst du hier durch eine Stored Procedure,
die das "Select " auf dem Server ausführt und somit nur ein Befehl übers Netz geht.

Weiter solltest du prüfen, ob auf den beiden Feldern auch Indizes liegen,
sonst wird ja ein full table scan aus dem Select.


Heiko

dbdeath74 11. Dez 2006 10:29

Re: Updates mit Zeos/MySQL dauert zu lange?
 
Hallo,

Die Felder sind indiziert, aber in diesem Fall mache ich ja den Locate auf dem lokalen Dataset, das hat gar nichts mit dem Server zu tun.
Das mache ich absichtlich um den Server zu entlasten, vor allem da ich sicher sein kann das ich der einzige bin der auf die Datenbank schreibend zugreift.

Ich hatte das bei der Optimierung der Applikation für den MSSQL Server mal eingeführt, da ich feststellen musste das meine Anwendung immer auf den MSSQL Server warten muss und nicht voll ausgelastet ist.

Hat mir damals Geschwindigkeitsvorteile gebracht. Aber wie gesagt, das lokale Dataset, das bei mySQL und MSSQL Version gleich ist, kann ja nicht für den Geschwindigkeitsunterschied verantwortlich sein.

Ein Update im Query Browser abzuschicken wird nicht viel bringen, es ist ja nicht das einzelne Update das solange dauert, sonder halt 100 davon.

Nach dem Tip mit dem Speicherverbrauch habe ich mir mal die Einstellungen angesehn des mySQL servers (Standardinstallation), und es war wirklich sehr wenig Speicher allokiert.

Also habe ich mal unter General Parameters die Memory Usage und unter InnoDB das Memory hochgedreht. Nach dem Neustart des Dienstes(der ewig braucht) hat es wohl irgendwas zerschossen :( *grr Alle InnoDB Tabellen gehen gar nicht, da InnoDB anscheinend nicht mehr geht. Muss mal schauen was er jetzt für Probleme hat, so viel höher hatte ich das Memory gar nicht gedreht, insgesamt immer noch nur ca 1/3 des max verfügbaren Speichers.

Hat jemand Tips zu den Einstellungen?

Gruß Oliver

Bernhard Geyer 11. Dez 2006 10:52

Re: Updates mit Zeos/MySQL dauert zu lange?
 
Zitat:

Zitat von dbdeath74
Ein Update im Query Browser abzuschicken wird nicht viel bringen, es ist ja nicht das einzelne Update das solange dauert, sonder halt 100 davon.

Ach da ist noch eine Schleife drüber? Dann schnelle deine Query auf parametrisierte Abfrage umstellen und Preparen. Sollte einiges bringen (auch beim MS SQL-Server)

hoika 11. Dez 2006 10:54

Q
 
Hallo,

zu mysql kann ich nichts sagen,
aber, wen du 100 mal die Query aufrufst,
muss der Server 100mal die Query parsen und einen SQL-Plan erzeugen.
Benutze mal prepared Queries.

Bsp:

zuerst preparen, dass kann man auch mit dem Aufruf verbinden,
indem die InsertQuery zuerst NIL ist,
und bei =NIL erzeugt und prepared wird

Delphi-Quellcode:
with InsertQuery do
begin
  SQL.Clear;
  SQL.Add('UPDATE CMDB_Software_Scan SET LastScan =:ScanDate, ');
  SQL.Add(', Aktiv = 1');
  SQL.Add(' WHERE ID = :ID'
  Prepare;
end;
und Nutzung
Delphi-Quellcode:
with InsertQuery do
begin
  ParamByName('ScanDate').AsDateTime:= scanDate;
  ParamByName('Id').AsInteger:= ScanId;
  ExecSQL;
end;
Wie du siehst, wird eine eigene Query benutzt.

Bei Firebird bekommt man hier in der Regel 100% mehr Performance.


Heiko

dbdeath74 12. Dez 2006 09:43

Re: Q
 
Zitat:

Zitat von hoika
Hallo,

zu mysql kann ich nichts sagen,
aber, wen du 100 mal die Query aufrufst,
muss der Server 100mal die Query parsen und einen SQL-Plan erzeugen.
Benutze mal prepared Queries.

Heiko

Hallo,

danke für den Tip :)
Hört sich sinnig an *g

Werde das mal bei meinen ADO Querys mit MSSQL testen (da gibt es prepared).

Bei den Zeos Querys die ich für den mySQL verwende finde ich es leider nicht :(
Auch nichts was sich anhört als würde es in Richtung prepare gehen *gr.

Weiß jemand wie man Zeos Querys für mySQL preparen kann?

Gruß Oliver

hoika 12. Dez 2006 10:31

Re: Updates mit Zeos/MySQL dauert zu lange?
 
Hallo,

so wie es in den Quellen (6.5.1. Alpha) aussieht,
wird immer prepared.
Ab 4.1 wird das Prepare von mysql übrigens erst unterstützt.

Solange das Statement sich nicht ändert,
bleibt die Query prepared.
Das heisst in deinem Fall, einfach eine parametrisierte Query
benutzen und den SQL-Text NICHT jedesmal zuweisen,
oder anderes gesagt.
Nimm eine separate Query, schreibe den SQL-Text (parametrisiert) einmal rein
und rufe dann immer nur Open bzw. Execute auf.


Heiko
PS: es muss doch auch nen SQL-Monitor geben,
wo man das Preparen der Query sehen kann.
Ich gehe ohne den sqlmonitor gar nicht ausser Haus ;)

dbdeath74 13. Dez 2006 10:49

Re: Updates mit Zeos/MySQL dauert zu lange?
 
Zitat:

Zitat von hoika
Hallo,

so wie es in den Quellen (6.5.1. Alpha) aussieht,
wird immer prepared.
Ab 4.1 wird das Prepare von mysql übrigens erst unterstützt.

Solange das Statement sich nicht ändert,
bleibt die Query prepared.
Das heisst in deinem Fall, einfach eine parametrisierte Query
benutzen und den SQL-Text NICHT jedesmal zuweisen,
oder anderes gesagt.
Nimm eine separate Query, schreibe den SQL-Text (parametrisiert) einmal rein
und rufe dann immer nur Open bzw. Execute auf.


Heiko
PS: es muss doch auch nen SQL-Monitor geben,
wo man das Preparen der Query sehen kann.
Ich gehe ohne den sqlmonitor gar nicht ausser Haus ;)

Hallo,

hörte sich in der Theorie klasse an *g :)

Hat leider fast keine Geschwindigkeitsvorteile gebracht :(

Gruß Oliver

hoika 13. Dez 2006 13:07

Re: Updates mit Zeos/MySQL dauert zu lange?
 
Hallo,

dann zeige doch noch mal diese Stelle,
wie sieht es eigentlich mit Transaktionen aus ?
Vor der Schleife StartTransaction und danach ein Commit;

Und knips endlich den SQL-Monitor an ;)


Heiko

dbdeath74 13. Dez 2006 14:37

Re: Updates mit Zeos/MySQL dauert zu lange?
 
Hallo,

öhmm welchen SQL Monitor meinst du?
Für mySQL kenne ich nur das was mir der mySQL Administrator mitliefert.

Hier mal 3 Sekunden Ausschnitt mit parametriesiertem Query.
Benutzt wird ZQuery Komponente. Meine Applikation bremst es auch nicht, die langweilt sich bei 5% Prozessorlast.
Beim der MSSQL version habe ich an dieser Stelle Prozessorlast ca 80%, einfach weil es viel schneller geht und er viel mehr zu tun hat.

MySQL schafft einfach nicht mehr wie ca 10 Updates pro sekunde :(
Aber auch der mySQL Dienst langweilt sich und hat kaum Prozessorauslastung(5%).

Die Tabelle aufm mySQL ist im InnoDB Format, hat einfach 4 Integer, 2 varchars und ein bit feld. Primary Key ist auf der ID über die ich ja auch das Update mache.
Ansonsten hat die Tabelle nur noch einen weiteren Index auf ein weiteres Feld das ich woanderst häufig zur Suche brauche.

Ich frage mich halt wer hier auf wenn und warum wartet *g

So baue ich die Query jetzt auf:
Delphi-Quellcode:
with QryLastScan do
    begin
      SQL.Clear;
      SQL.Add('UPDATE CMDB_Software_Scan SET LastScan =:ScanDate ');
      SQL.Add(', Aktiv = 1');
      SQL.Add(' WHERE ID = :ID');
    end;
Und so Rufe ich sie auf:
Delphi-Quellcode:
with QryLastScan do
begin
  ParamByName('ScanDate').AsString := QuotedStr(DateTimeToStr(scanDate));
  ParamByName('Id').AsInteger:= ScanId;
  ExecSQL;
end;
Und hier mal ein 3sec AUsschnitt ausm mySQL Administrator

SQL-Code:
061213 13:29:09         5 Query      UPDATE CMDB_Software_Scan SET LastScan ='\'13.12.2006 13:10:58\'' , Aktiv = 1 WHERE ID = 2240
            5 Query      UPDATE CMDB_Software_Scan SET LastScan ='\'13.12.2006 13:10:58\'' , Aktiv = 1 WHERE ID = 2241
            5 Query      UPDATE CMDB_Software_Scan SET LastScan ='\'13.12.2006 13:10:58\'' , Aktiv = 1 WHERE ID = 2242
            5 Query      UPDATE CMDB_Software_Scan SET LastScan ='\'13.12.2006 13:10:58\'' , Aktiv = 1 WHERE ID = 2243
            5 Query      UPDATE CMDB_Software_Scan SET LastScan ='\'13.12.2006 13:10:58\'' , Aktiv = 1 WHERE ID = 2244
            5 Query      UPDATE CMDB_Software_Scan SET LastScan ='\'13.12.2006 13:10:58\'' , Aktiv = 1 WHERE ID = 2245
            5 Query      UPDATE CMDB_Software_Scan SET LastScan ='\'13.12.2006 13:10:58\'' , Aktiv = 1 WHERE ID = 2246
            5 Query      UPDATE CMDB_Software_Scan SET LastScan ='\'13.12.2006 13:10:58\'' , Aktiv = 1 WHERE ID = 2247
            5 Query      UPDATE CMDB_Software_Scan SET LastScan ='\'13.12.2006 13:10:58\'' , Aktiv = 1 WHERE ID = 2248
            5 Query      UPDATE CMDB_Software_Scan SET LastScan ='\'13.12.2006 13:10:58\'' , Aktiv = 1 WHERE ID = 2249
061213 13:29:10         5 Query      UPDATE CMDB_Software_Scan SET LastScan ='\'13.12.2006 13:10:58\'' , Aktiv = 1 WHERE ID = 2250
            5 Query      UPDATE CMDB_Software_Scan SET LastScan ='\'13.12.2006 13:10:58\'' , Aktiv = 1 WHERE ID = 2251
            5 Query      UPDATE CMDB_Software_Scan SET LastScan ='\'13.12.2006 13:10:58\'' , Aktiv = 1 WHERE ID = 2252
            5 Query      UPDATE CMDB_Software_Scan SET LastScan ='\'13.12.2006 13:10:58\'' , Aktiv = 1 WHERE ID = 2253
            5 Query      UPDATE CMDB_Software_Scan SET LastScan ='\'13.12.2006 13:10:58\'' , Aktiv = 1 WHERE ID = 2254
            5 Query      UPDATE CMDB_Software_Scan SET LastScan ='\'13.12.2006 13:10:58\'' , Aktiv = 1 WHERE ID = 2255
            5 Query      UPDATE CMDB_Software_Scan SET LastScan ='\'13.12.2006 13:10:58\'' , Aktiv = 1 WHERE ID = 2256
            5 Query      UPDATE CMDB_Software_Scan SET LastScan ='\'13.12.2006 13:10:58\'' , Aktiv = 1 WHERE ID = 2257
            5 Query      UPDATE CMDB_Software_Scan SET LastScan ='\'13.12.2006 13:10:58\'' , Aktiv = 1 WHERE ID = 2258
            5 Query      UPDATE CMDB_Software_Scan SET LastScan ='\'13.12.2006 13:10:58\'' , Aktiv = 1 WHERE ID = 2259
            5 Query      UPDATE CMDB_Software_Scan SET LastScan ='\'13.12.2006 13:10:58\'' , Aktiv = 1 WHERE ID = 2260
061213 13:29:11         5 Query      UPDATE CMDB_Software_Scan SET LastScan ='\'13.12.2006 13:10:58\'' , Aktiv = 1 WHERE ID = 2261
            5 Query      UPDATE CMDB_Software_Scan SET LastScan ='\'13.12.2006 13:10:58\'' , Aktiv = 1 WHERE ID = 2262
            5 Query      UPDATE CMDB_Software_Scan SET LastScan ='\'13.12.2006 13:10:58\'' , Aktiv = 1 WHERE ID = 2263
            5 Query      UPDATE CMDB_Software_Scan SET LastScan ='\'13.12.2006 13:10:58\'' , Aktiv = 1 WHERE ID = 2264
            5 Query      UPDATE CMDB_Software_Scan SET LastScan ='\'13.12.2006 13:10:58\'' , Aktiv = 1 WHERE ID = 2265
            5 Query      UPDATE CMDB_Software_Scan SET LastScan ='\'13.12.2006 13:10:58\'' , Aktiv = 1 WHERE ID = 2266
            5 Query      UPDATE CMDB_Software_Scan SET LastScan ='\'13.12.2006 13:10:58\'' , Aktiv = 1 WHERE ID = 2267
            5 Query      UPDATE CMDB_Software_Scan SET LastScan ='\'13.12.2006 13:10:58\'' , Aktiv = 1 WHERE ID = 2268
            5 Query      UPDATE CMDB_Software_Scan SET LastScan ='\'13.12.2006 13:10:58\'' , Aktiv = 1 WHERE ID = 2269
            5 Query      UPDATE CMDB_Software_Scan SET LastScan ='\'13.12.2006 13:10:58\'' , Aktiv = 1 WHERE ID = 2270
Ich habe jetzt mal testweise etwas gebastelt mit directSQL. Der Schafft auch nicht mehr wie 10 Updates pro sekunde :(

Transaktionen verwende ich nicht, da ich erstens alleine schreibzugriff habe und zweitens einfach nur ein Update machen will :p
Transaktionen sollten doch auch meines Wissens nichts mit der Geschwindigkeit zu tun haben, sondern es eher noch langsamer machen weil er ja Rollbackpunkte etc... bereithalten muss. Lasse mich aber gerne eines besseren belehren :)

Gruß Oliver

Thanatos81 13. Dez 2006 14:49

Re: Updates mit Zeos/MySQL dauert zu lange?
 
Bei den Zeos gibt es eine Komponente TZSQLMonitor. Falls diese aktiv ist protokolliert die alle Befehle und Fehlermeldungen mit, die über deine TZConnection wandern ;-) Falls man nur bestimmte Meldungen protokollieren will, sollte man sich das Ereignis OnLogTrace anschauen.

hoika 13. Dez 2006 14:53

Re: Updates mit Zeos/MySQL dauert zu lange?
 
Hallo,

also unter Firebird (BDE, jaja ;) ) ist das so:

Wird keine Transaktion manuell (DataBase.StartTransaction) gestartet,
erzeugt die BDE für JEDE Abfrage eine Transaktion und Committed die.
Das ist bei bestimmten Sachen um Faktor 20 langsamer,
als einmal eine Transaktion zu starten,
alle Updates machen und dann Committen.

Sind die IDs eigentlich immer aufsteigend ohne Lücken ?
Dann würde ja ein Where Id>=Min and Id<=Max reichen ;) :coder:

Heiko

dbdeath74 13. Dez 2006 15:54

Re: Updates mit Zeos/MySQL dauert zu lange?
 
Zitat:

Zitat von hoika
Hallo,

also unter Firebird (BDE, jaja ;) ) ist das so:

Wird keine Transaktion manuell (DataBase.StartTransaction) gestartet,
erzeugt die BDE für JEDE Abfrage eine Transaktion und Committed die.
Das ist bei bestimmten Sachen um Faktor 20 langsamer,
als einmal eine Transaktion zu starten,
alle Updates machen und dann Committen.

Sind die IDs eigentlich immer aufsteigend ohne Lücken ?
Dann würde ja ein Where Id>=Min and Id<=Max reichen ;) :coder:

Heiko

Hallo,

GENIAL !!!! :love: :dp: :mrgreen:

Faktor 20 ist gar kein Ausdruck *g hab jetzt 1/3 Sekunde pro Gerät statt 8 sec.
Er macht wirklich wenn man nichts sagt jedesmal eine Transaction.

Achja, MSSQL mit ADO Komponenten macht dies anscheinend nicht. Hier brachte Transaktion keinerlei Vorteile.

Und nein die IDs sind nicht immer aufsteigend, das war nur Zufall weil es auf der Testversion war.

Gruß Oliver

hoika 13. Dez 2006 16:34

Re: Updates mit Zeos/MySQL dauert zu lange?
 
Hm,

jetzt habe ich dich noch mehr an mysql rangebracht,
statt dich für Firebird zu begeistern, ich Dussel ;)

Egal. :cheers:


Heiko


Alle Zeitangaben in WEZ +1. Es ist jetzt 10:34 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