![]() |
Datenbank: MsSQL • Version: 2008R2 • Zugriff über: UniDac
Daten ohne Zeitverzögerung speichern
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:
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.
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; 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 |
AW: Daten ohne Zeitverzögerung speichern
Am einfachsten wäre wohl ein FiFo-Stack, der das Bindeglied zwischen Lesen und Wegschreiben bildet.
Gruß K-H |
AW: Daten ohne Zeitverzögerung speichern
Ist Deine Delphi Version wie im Profil angegeben XE?
Mavarik |
AW: Daten ohne Zeitverzögerung speichern
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 |
AW: Daten ohne Zeitverzögerung speichern
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 |
AW: Daten ohne Zeitverzögerung speichern
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, ...). |
AW: Daten ohne Zeitverzögerung speichern
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:
oder sogar- glaub sql server kann das
begin
insert into mytable [feldliste*] values (werteliste); insert into mytable [feldliste*] values (werteliste); insert into mytable [feldliste*] values (werteliste); .. end
Code:
* feldliste kann man aus Platzgründen vlt auch weglassen, wenn vollständige Werteliste da ist und sichergestellt, dass es zusammenpasst.
begin
insert into mytable [feldliste*] values ((werteliste); (werteliste); (werteliste)); .. end 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, ..) |
AW: Daten ohne Zeitverzögerung speichern
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:
zusätzlich kommt dahinter ein
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');
Delphi-Quellcode:
Und beim Schreiben der Daten dann nur noch die Parameter füllen
dmFCalib.dbquQuery.Prepared;
Delphi-Quellcode:
Das reduziert die Netzlast.
// 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; 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 |
AW: Daten ohne Zeitverzögerung speichern
Hallo
Zitat:
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 Zitat:
Wäre so was denkbar:
Delphi-Quellcode:
Hat noch jemand einen Ansatz(Code) für den Thread incl. Connection?
// 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; Danke Gerd |
AW: Daten ohne Zeitverzögerung speichern
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 |
Alle Zeitangaben in WEZ +1. Es ist jetzt 21:58 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 by Thomas Breitkreuz