AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Datenbanken Daten ohne Zeitverzögerung speichern
Thema durchsuchen
Ansicht
Themen-Optionen

Daten ohne Zeitverzögerung speichern

Ein Thema von norwegen60 · begonnen am 4. Mär 2016 · letzter Beitrag vom 4. Mär 2016
Antwort Antwort
norwegen60

Registriert seit: 23. Dez 2007
Ort: Schwarzwald
505 Beiträge
 
Delphi 12 Athens
 
#1

Daten ohne Zeitverzögerung speichern

  Alt 4. Mär 2016, 12:46
Datenbank: MsSQL • Version: 2008R2 • Zugriff über: UniDac
Hallo zusammen,

ich habe eine Anwendung in der Timergesteuert (100ms) Messdaten erfasst und in eine DB gespeichert werden. Bei LAN-Zugriff ist das auch ausreichend schnell. Jetzt ist aber ein Rechner nur über WLan verbunden und da habe ich das Problem, dass es manchmal bis zu 2000ms dauert, bis die Daten gespeichert und damit der Timer für den nächsten Prozess freigegeben ist. (Timerereignis ist für Folge-Ereignisse gesperrt bis ein Prozess komplett abgeschlossen ist.)

Ich dachte, dass sich das über
Delphi-Quellcode:
         dmFCalib.dbquQuery.SQL.Text := 'BEGIN TRAN';
          dmFCalib.dbquQuery.SQL.Add('INSERT INTO [Cal_Force] ');
          dmFCalib.dbquQuery.SQL.Add('([CalReportID], [FAct], [FTarget], [Art], [Temperatur], [Humidity], [ServOrt], [ErstUserID], [ErstDat])');
          dmFCalib.dbquQuery.SQL.Add('VALUES');
          dmFCalib.dbquQuery.SQL.Add('(:pCalReportID, :pFAct, :pFTarget, :pArt, :pTemperatur, :pHumidity, :pServOrt, :pErstUserID, GETDATE())');
          dmFCalib.dbquQuery.SQL.Add('COMMIT TRAN');

          // set query parameters
          dmFCalib.dbquQuery.ParamByName('pCalReportID').Value := dmFCalib.dbquCalReport.FieldByName('ID').AsInteger;
          dmFCalib.dbquQuery.ParamByName('pFAct').Value := rForce;
          dmFCalib.dbquQuery.ParamByName('pFTarget').Value := rFtarget;
          dmFCalib.dbquQuery.ParamByName('pArt').Value := cArt;
          dmFCalib.dbquQuery.ParamByName('pTemperatur').Value := uHilfs1.Valreal(edTemperatur.Text);
          dmFCalib.dbquQuery.ParamByName('pHumidity').Value := uHilfs1.ValReal(edHumidity.Text);
          dmFCalib.dbquQuery.ParamByName('pServOrt').Value := cServOrt;
          dmFCalib.dbquQuery.ParamByName('pErstUserID').Value := intUser.User.ID;

          dmFCalib.dbquQuery.ExecSQL;
bessert. Die durchschnittliche Zeit für die Ausführung dieses Blocks sinkt auch von 12ms auf 5ms und die Aussetzer sind auch reduziert, aber es gibt sie immer noch.

Wie bekomme ich es hin, dass das Wegschreiben der Daten den Prozess gar nicht beeinflusst. Bei der Verwendung von Threads zusammen mit Datenbankverbindungen habe ich schon die tollsten Sachen gelesen und da ich mit Threading noch nicht vertiefend befasst habe, wäre ich froh, wenn ich hier ein Beispielthread bekommen würde.

Das direkte Wegschreiben der Daten hat den großen Vorteil, dass an einem anderen Arbeitsplatz die Daten mehr oder weniger online beobachtet werden könne

Vielen Dank
Gerd
  Mit Zitat antworten Zitat
Benutzerbild von p80286
p80286

Registriert seit: 28. Apr 2008
Ort: Stolberg (Rhl)
6.659 Beiträge
 
FreePascal / Lazarus
 
#2

AW: Daten ohne Zeitverzögerung speichern

  Alt 4. Mär 2016, 12:57
Am einfachsten wäre wohl ein FiFo-Stack, der das Bindeglied zwischen Lesen und Wegschreiben bildet.

Gruß
K-H
Programme gehorchen nicht Deinen Absichten sondern Deinen Anweisungen
R.E.D retired error detector
  Mit Zitat antworten Zitat
Benutzerbild von Mavarik
Mavarik

Registriert seit: 9. Feb 2006
Ort: Stolberg (Rhld)
4.144 Beiträge
 
Delphi 10.3 Rio
 
#3

AW: Daten ohne Zeitverzögerung speichern

  Alt 4. Mär 2016, 12:57
Ist Deine Delphi Version wie im Profil angegeben XE?

Mavarik
  Mit Zitat antworten Zitat
AndyDF

Registriert seit: 6. Sep 2006
Ort: Allgäu
99 Beiträge
 
Delphi 10.4 Sydney
 
#4

AW: Daten ohne Zeitverzögerung speichern

  Alt 4. Mär 2016, 12:57
Hallo Gerd,

also ich schreibe und lese permanent Daten aus der Datenbank innerhalb eines Thread. Das funktioniert super, wenn man auf ein paar Dinge achtet.
Wichtig ist, dass alles, was zu dem jeweiligen Schreib- bzw. Lesevorgang gehört, nur von einem Thread verwendet wird. (Connection, Transaction, Query, ..). Also am Besten gleich die gesamte DB Verbindung innerhalb des Threads erzeugen und wieder verwerfen.

Viele Grüße, Andreas
Andreas Blenk
  Mit Zitat antworten Zitat
norwegen60

Registriert seit: 23. Dez 2007
Ort: Schwarzwald
505 Beiträge
 
Delphi 12 Athens
 
#5

AW: Daten ohne Zeitverzögerung speichern

  Alt 4. Mär 2016, 13:23
Hallo,

Delphi Version ist XE3

Was ist mit den Hinweisen, dass innerhalb einer Anwendug keine zwei Connections auf die DB gemacht werden sollen. Wenn der Thraed seine eigene bekommt, sind es bei mir zwei. Das Program ist noch altherkömmlich mit DB-Eingabefeldern programmiert.

Hättest du Code wie der Thraed aussehen müsste. Wie gesagt habe ich mich mit denen noch nicht vertiefend befasst

Danke
Gerd
  Mit Zitat antworten Zitat
Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#6

AW: Daten ohne Zeitverzögerung speichern

  Alt 4. Mär 2016, 14:12
Wenn die DB einen Multi-User-Zugriff verkraftet, dann kannst du so viele Connections zu der aufbauen, wie du am DB-System zugelassen hast.

Jede Connection sollte aber nur innerhalb eines Thread-Kontexts gleichzeitig verwendet werden, weil man sich sonst mit den Transaktionen verheddert.

Eine Queue ist da schon das Mittel der Wahl ... allerdings solltest du dir etwas überlegen, was du machst, wenn sich die Daten extrem stauen. Wenn du alle 100ms einen Datensatz erzeugst und alle ca. 1000ms zum Schreiben eines Datensatz benötigst, dann kann man sich die Zeit ausrechnen, wann der Speicher nicht mehr ausreicht. Dann muss man entweder Daten auslassen oder zwischenspeichern (Datei, lokale DB, ...).
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)

Geändert von Sir Rufo ( 4. Mär 2016 um 14:17 Uhr)
  Mit Zitat antworten Zitat
jobo

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

AW: Daten ohne Zeitverzögerung speichern

  Alt 4. Mär 2016, 14:29
Ich weiß nicht, ob das komponentenspezifisch ist, aber gefühlt gibt es in der Kommunikation viel Overhead/Kleinkram, sagen wir mal, das läuft recht geschwätzig und das tut dann spätestens im WLAN weh, Unidac habe ich aber noch nie benutzt.

Multithreading macht das nicht unbedingt besser, weil gleiche Zugriffs-Technik, es läuft nur asynchron.
Ich würde daher vielleicht versuchen, die einzelnen Queries mit mehr Daten zu beladen, bei einem Query gleicher Overhead, aber mehr "Nutzlast". Dafür müsste man allerdings auf Parametrierung verzichten. Soweit ich weiß kann SQL Server anonyme Blöcke. Das ergäbe soetwas in der Art in einer Query:
Code:
begin
insert into mytable [feldliste*] values (werteliste);
insert into mytable [feldliste*] values (werteliste);
insert into mytable [feldliste*] values (werteliste);
..
end
oder sogar- glaub sql server kann das
Code:
begin
insert into mytable [feldliste*] values ((werteliste);
                                         (werteliste);
                                         (werteliste));
..
end
* feldliste kann man aus Platzgründen vlt auch weglassen, wenn vollständige Werteliste da ist und sichergestellt, dass es zusammenpasst.

Ich könnte mir vorstellen, dass einzelne Queries mit 5, 10 -50 Sätzen ähnlich schnell verarbeitet werden, wie ein einzelner Satz jetzt bei Dir.

Serverseitig könnte man ggF. noch prüfen, ob die Tabellenstruktur für schnelle inserts geeignet ist (wenig/kein Index, ..)
Gruß, Jo
  Mit Zitat antworten Zitat
hoika

Registriert seit: 5. Jul 2006
Ort: Magdeburg
8.276 Beiträge
 
Delphi 10.4 Sydney
 
#8

AW: Daten ohne Zeitverzögerung speichern

  Alt 4. Mär 2016, 17:01
Hallo,
du erzeugst die Query ja jedes mal neu auf dem Server.
Probiere doch mal eine prepared Query aus.

Beim Start ds Programmes machst du dein

Delphi-Quellcode:
dmFCalib.dbquQuery.SQL.Text := 'BEGIN TRAN';
dmFCalib.dbquQuery.SQL.Add('INSERT INTO [Cal_Force] ');
dmFCalib.dbquQuery.SQL.Add('([CalReportID], [FAct], [FTarget], [Art], [Temperatur], [Humidity], [ServOrt], [ErstUserID], [ErstDat])');
dmFCalib.dbquQuery.SQL.Add('VALUES');
dmFCalib.dbquQuery.SQL.Add('(:pCalReportID, :pFAct, :pFTarget, :pArt, :pTemperatur, :pHumidity, :pServOrt, :pErstUserID, GETDATE())');
dmFCalib.dbquQuery.SQL.Add('COMMIT TRAN');
zusätzlich kommt dahinter ein
dmFCalib.dbquQuery.Prepared; Und beim Schreiben der Daten dann nur noch die Parameter füllen

Delphi-Quellcode:
// set query parameters
dmFCalib.dbquQuery.ParamByName('pCalReportID').Value := dmFCalib.dbquCalReport.FieldByName('ID').AsInteger;
dmFCalib.dbquQuery.ParamByName('pFAct').Value := rForce;
dmFCalib.dbquQuery.ParamByName('pFTarget').Value := rFtarget;
dmFCalib.dbquQuery.ParamByName('pArt').Value := cArt;
dmFCalib.dbquQuery.ParamByName('pTemperatur').Value := uHilfs1.Valreal(edTemperatur.Text);
dmFCalib.dbquQuery.ParamByName('pHumidity').Value := uHilfs1.ValReal(edHumidity.Text);
dmFCalib.dbquQuery.ParamByName('pServOrt').Value := cServOrt;
dmFCalib.dbquQuery.ParamByName('pErstUserID').Value := intUser.User.ID;

dmFCalib.dbquQuery.ExecSQL;
Das reduziert die Netzlast.

Schneller wäre dann noch eine stored procedure oder bulk insert.

Die Query dient damit ausschließlich diesem Insert.
Hast du mehr davon -> mehrere Queries benutzen.


Soweit ich nicht erinnere, cacht der sql-server aber parametrisierte Queries selbst,
aber einen Versuch ist es Wert.


Heiko
Heiko
  Mit Zitat antworten Zitat
norwegen60

Registriert seit: 23. Dez 2007
Ort: Schwarzwald
505 Beiträge
 
Delphi 12 Athens
 
#9

AW: Daten ohne Zeitverzögerung speichern

  Alt 4. Mär 2016, 18:45
Hallo

... allerdings solltest du dir etwas überlegen, was du machst, wenn sich die Daten extrem stauen. ...).
Da habe ich an zwei Möglichkeiten gedacht:
Zuerst werde ich eine gwisse Anzahl zwischenspeichern und wenn zu viele Daten ankommen, werde ich den Zwischenspeicher immer wieder mal löschen. Es ist kein absolutes Muss, dass immer alle Daten gespeichert werden

zusätzlich kommt dahinter ein
dmFCalib.dbquQuery.Prepared;
Das kannte ich noch nicht. Werde ich mal probieren. Was passiert hier, wenn ich ExecSQL aufrufe wenn der vorherige Aufruf noch nicht beendet ist?
Wäre so was denkbar:
Delphi-Quellcode:
// set query parameters
if iCount < 10 then
begin
  inc(iCount);
  
  dmFCalib.dbquQuery.ParamByName('pCalReportID').Value := dmFCalib.dbquCalReport.FieldByName('ID').AsInteger;
  dmFCalib.dbquQuery.ParamByName('pFAct').Value := rForce;
  dmFCalib.dbquQuery.ParamByName('pFTarget').Value := rFtarget;
  dmFCalib.dbquQuery.ParamByName('pArt').Value := cArt;
  dmFCalib.dbquQuery.ParamByName('pTemperatur').Value := uHilfs1.Valreal(edTemperatur.Text);
  dmFCalib.dbquQuery.ParamByName('pHumidity').Value := uHilfs1.ValReal(edHumidity.Text);
  dmFCalib.dbquQuery.ParamByName('pServOrt').Value := cServOrt;
  dmFCalib.dbquQuery.ParamByName('pErstUserID').Value := intUser.User.ID;

  dmFCalib.dbquQuery.ExecSQL;
  dec(iCount);
end;
Hat noch jemand einen Ansatz(Code) für den Thread incl. Connection?

Danke
Gerd

Geändert von norwegen60 ( 4. Mär 2016 um 19:04 Uhr)
  Mit Zitat antworten Zitat
hoika

Registriert seit: 5. Jul 2006
Ort: Magdeburg
8.276 Beiträge
 
Delphi 10.4 Sydney
 
#10

AW: Daten ohne Zeitverzögerung speichern

  Alt 4. Mär 2016, 21:59
Hallo,

< Was passiert hier, wenn ich ExecSQL aufrufe wenn der vorherige Aufruf noch nicht beendet ist? >

Wie soll das passieren, der Thread führt seinen eigenen Code Zeile für Zeile nacheinander aus,
aber halt parallel zum Haupt-Thread.


Heiko
Heiko
  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 04:16 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