Aktualisierungsabfrage nur für geänderte Werte?
Hallo zusammen,
ich habe da mal eine Frage - bisher waren meine Datenmengen immer recht überschaubar. Mit den Projekten wachsen aber auch Anforderungen und bei mir manchmal die Fragezeichen.
Ich habe eine Tabelle mit knapp einer Million Datensätzen, Tendenz stark steigend. Bisher habe ich mich nur ums Anfügen der Daten gekümmert - aber da es sich um eine Schnittstelle handelt können sich die vorhandenen Daten natürlich auch geändert haben.
Nun meine Preisfrage : Gibt es eine Möglichkeit nicht immer alle Werte der ganzen Tabelle aktualisieren zu müssen, die ich vielleicht nicht kenne?
Mein erster Gedanke war es, einen Hashwert vom Tupel zu ziehen und den zu vergleichen - aber ganz überzeugt bin ich da noch nicht von mir.
Mein zweiter Gedanke war die Idee das mit 3-4 Abfragen auf unterschiedliche, zu erwartende Änderungsfelder zu setzen und diese einfach 1:1 zu vergleichen.
Mein dritter Gedanke war, einen Post hier abzusetzen bevor ich Zeit mit der Umsetzung einer zum Scheitern verurteilten Idee verschwende.
Wie würdet Ihr sowas lösen?
Ich freue mich über Anregungen!
Solong, Sascha
ich habe da mal eine Frage - bisher waren meine Datenmengen immer recht überschaubar. Mit den Projekten wachsen aber auch Anforderungen und bei mir manchmal die Fragezeichen.
Ich habe eine Tabelle mit knapp einer Million Datensätzen, Tendenz stark steigend. Bisher habe ich mich nur ums Anfügen der Daten gekümmert - aber da es sich um eine Schnittstelle handelt können sich die vorhandenen Daten natürlich auch geändert haben.
Nun meine Preisfrage : Gibt es eine Möglichkeit nicht immer alle Werte der ganzen Tabelle aktualisieren zu müssen, die ich vielleicht nicht kenne?
Mein erster Gedanke war es, einen Hashwert vom Tupel zu ziehen und den zu vergleichen - aber ganz überzeugt bin ich da noch nicht von mir.
Mein zweiter Gedanke war die Idee das mit 3-4 Abfragen auf unterschiedliche, zu erwartende Änderungsfelder zu setzen und diese einfach 1:1 zu vergleichen.
Mein dritter Gedanke war, einen Post hier abzusetzen bevor ich Zeit mit der Umsetzung einer zum Scheitern verurteilten Idee verschwende.
Wie würdet Ihr sowas lösen?
Ich freue mich über Anregungen!
Solong, Sascha
Bitte markiere auch die Kommentare, die zur Lösung des Beitrags beigetragen haben
Content-ID: 3122731355
Url: https://administrator.de/contentid/3122731355
Ausgedruckt am: 05.11.2024 um 04:11 Uhr
16 Kommentare
Neuester Kommentar
und hier kommt es auch drauf an was für daten es sind... im dümmsten Fall machst halt (da keiner deine anwendung kennt kann man nur grobe Ideen geben) nen zusätzliches feld rein: "Last update" mit nem Timestamp. Wenn du jetzt also nur Daten aktuallisieren willst die nicht in den letzten 24h schon gemacht wurden: where lastupdate <= now - 24h (genaue syntax kannst du dir ja raussuchen)
geht natürlich auch andersrum - da hängt es einfach von deiner Anwendung ab was da Sinn macht...
geht natürlich auch andersrum - da hängt es einfach von deiner Anwendung ab was da Sinn macht...
Hallo Sascha,
ich habe das Thema für mich so gelöst.
Entweder ich kann den Daten ein zusätzliches Feld als "Flag" mitgeben, dass ich entsprechend setzen kann oder wenn ich sehr viele Daten verarbeiten muss (egal ob Update oder Insert), dann lese ich diese zuerst in ein temporäre Tabelle und verarbeitet diese dann paketweise (modifiziere rowcount - z.B. set rowcount=100).
Das hat die Verarbeitungsgeschwindigkeit schon deutlich verbessert.
ich habe das Thema für mich so gelöst.
Entweder ich kann den Daten ein zusätzliches Feld als "Flag" mitgeben, dass ich entsprechend setzen kann oder wenn ich sehr viele Daten verarbeiten muss (egal ob Update oder Insert), dann lese ich diese zuerst in ein temporäre Tabelle und verarbeitet diese dann paketweise (modifiziere rowcount - z.B. set rowcount=100).
Das hat die Verarbeitungsgeschwindigkeit schon deutlich verbessert.
Hi,
ich verstehe es irgendwie nicht. Daten anfügen - ok. Wie sollen wir uns den Rest vorstellen? Ins blaue hinein wird irgendwas upgedated?
Was für eine Schnittstelle? Protkolliert sie die Änderungen? Normal mach sowas z.B. das ERP System dahinter. Anlege- und Änderungsdatum etc. sind Standard.
https://stackoverflow.com/questions/6344413/sql-server-row-date-last-mod ...
Da siehst du auch ein paar Ansätze. Aber welche DB hast du überhaupt? Was für Daten? Was soll denn aktualisiert werden? Bzw. was nicht.
Felder vergleichen geht. Es gibt Scripte/ Tools etc. die sowas machen. Du kannst auch 1 Mio in DB A und 1 Mio in DB B speichern und vergleichen. Frage nach den Sinn/ Geschwindigkeit/ Ressourcen kommen nur dann.....
https://docs.microsoft.com/de-de/sql/t-sql/functions/columns-updated-tra ...
Sowas geht bei MS SQL. Nach den Testen Aktion XY ausführen. .....
ich verstehe es irgendwie nicht. Daten anfügen - ok. Wie sollen wir uns den Rest vorstellen? Ins blaue hinein wird irgendwas upgedated?
Was für eine Schnittstelle? Protkolliert sie die Änderungen? Normal mach sowas z.B. das ERP System dahinter. Anlege- und Änderungsdatum etc. sind Standard.
https://stackoverflow.com/questions/6344413/sql-server-row-date-last-mod ...
Da siehst du auch ein paar Ansätze. Aber welche DB hast du überhaupt? Was für Daten? Was soll denn aktualisiert werden? Bzw. was nicht.
Felder vergleichen geht. Es gibt Scripte/ Tools etc. die sowas machen. Du kannst auch 1 Mio in DB A und 1 Mio in DB B speichern und vergleichen. Frage nach den Sinn/ Geschwindigkeit/ Ressourcen kommen nur dann.....
https://docs.microsoft.com/de-de/sql/t-sql/functions/columns-updated-tra ...
Sowas geht bei MS SQL. Nach den Testen Aktion XY ausführen. .....
Zitat von @TheUnreal:
Moin zusammen,
danke für die Beteiligung.Ich dachte ehrlich gesagt nicht, dass die Anwendung interessiert - warum auch, es gibt keine?
Es handelt sich um eine Schnittstelle zwischen einem alten (selbstentwickelten) ERP und einem neuen ERP.
Moin zusammen,
danke für die Beteiligung.Ich dachte ehrlich gesagt nicht, dass die Anwendung interessiert - warum auch, es gibt keine?
Es handelt sich um eine Schnittstelle zwischen einem alten (selbstentwickelten) ERP und einem neuen ERP.
Weil eine Schnittstelle alles sein kann. Einige bieten auch Log-Features ....
SQL Dialekt - Okay
Naja Nein. SQL 2000, 2008, etc... Gerade bei alten Systemen ist das Problem, dass es früher einige nützliche Funktionen nicht gab.
Da ist MsSQL auf der einen und Postgres per ODBC auf der anderen.
Schön. Wir haben einen Namen. Zwar noch keine Versionsnummer, aber immerhin.
Ich habe Daten (was auch immer - Text,Datum, Zahl -- is doch wurscht?!) in einer Tabelle und füge stumpf jeden Datensatz von MsTabelle an PostgresTabelle an.
Nein. Wenn man stumpf versucht 2x Zeilen - aucht mit Binäredaten o.ä. zu vergleichen gibt es Fehler. Die Art ist schon wichtig, je nachdem was man vergleichen möchte.
Trigger?
Es sollte festgestellt werden, wo Dokumente beim "Abzeichnen" liegen bleiben. Im System wurde Datum und Kürzel hinterlegt. Würde man die Daten nacheinander aufreihen so kann man die Zeitendifferenzen sichtbar machen. Mitarbeiter A und B tragen am 20.06.2022 umd 9:13 Uhr und um 11:20 Uhr was ein. Mitarbeiter C aber erst am 21.06.2022 um 08:15 Uhr.
Also lag der Vorgang über 12 Std. da rum.
Ist aus den Links oben zusammengeklaut. Server war hier MS SQL 2012.
Warum wichtig? Später verwendete ich zum Aufberreiten der Datensätze LAG Funktion. Damit war alles sauber sortiert und ich konnte die Zeiten vergleichen.
LAG:
Greift im selben Resultset auf Daten in einer vorherigen Zeile zu, ohne dass ein Selbstjoin ab SQL Server 2012 (11.x) verwendet wird.
Ab Server 2012... Nicht 2000 oder 2008 - darum auch immer die Frage welchen SQL Server die Leute einsetzen und in welcher Version.
Für Abgleiche ggf. noch welche Sprache/ Datumsformat. Sonst gehen Vergleiche in die Hose.
Log Tabelle die Änderungen protokolliert
use TolleDB
GO
DROP TABLE intern.dbo.auditE_BerichtHz;
DROP TRIGGER updE_Bericht;
CREATE TABLE intern.dbo.auditE_BerichtHz (
--audit_log_id uniqueidentifier DEFAULT NEWID() PRIMARY KEY,
audit_log_id INT NOT NULL IDENTITY PRIMARY KEY,
audit_log_type char (3) NOT NULL,
audit_pat_num int NOT NULL,
audit_kurz_sd char (5) NOT NULL,
audit_verlauf1 char (20) NOT NULL,
audit_verlauf2 char (20) NOT NULL,
audit_verlauf3 char (20) NOT NULL,
audit_verlauf4 char (20) NOT NULL,
audit_verlauf5 char (20) NOT NULL,
audit_verlauf6 char (20) NOT NULL,
audit_user sysname DEFAULT SUSER_SNAME(),
audit_changed datetime DEFAULT GETDATE()
);
GO
CREATE TRIGGER updE_Bericht ON [dbo].[e_bericht]
AFTER UPDATE AS
IF ( 1+2=3
--(SUBSTRING(COLUMNS_UPDATED(), 6, 1) & 31 > 0)
)
BEGIN
-- Audit OLD record.
INSERT INTO intern.dbo.auditE_BerichtHz
(audit_log_type, audit_pat_num,
audit_kurz_sd,
audit_verlauf1,
audit_verlauf2,
audit_verlauf3,
audit_verlauf4,
audit_verlauf5,
audit_verlauf6)
SELECT 'OLD',
del.pat_num,
del.kurz_sd,
del.verlauf1,
del.verlauf2,
del.verlauf3,
del.verlauf4,
del.verlauf5,
del.verlauf6
FROM deleted del
INNER JOIN inserted ins ON del.pat_num=ins.pat_num
WHERE ins.verlauf1<>del.verlauf1 OR
ins.verlauf2<>del.verlauf2 OR
ins.verlauf3<>del.verlauf3 OR
ins.verlauf4<>del.verlauf4 OR
ins.verlauf5<>del.verlauf5 OR
ins.verlauf6<>del.verlauf6 OR
ins.kurz_sd<>del.kurz_sd;
-- Audit NEW record.
INSERT INTO intern.dbo.auditE_BerichtHz
(audit_log_type,audit_pat_num,
audit_kurz_sd,
audit_verlauf1,
audit_verlauf2,
audit_verlauf3,
audit_verlauf4,
audit_verlauf5,
audit_verlauf6)
SELECT 'NEW',
ins.pat_num,
ins.kurz_sd,
ins.verlauf1,
ins.verlauf2,
ins.verlauf3,
ins.verlauf4,
ins.verlauf5,
ins.verlauf6
FROM deleted del
INNER JOIN inserted ins ON del.pat_num=ins.pat_num
WHERE ins.verlauf1<>del.verlauf1 OR
ins.verlauf2<>del.verlauf2 OR
ins.verlauf3<>del.verlauf3 OR
ins.verlauf4<>del.verlauf4 OR
ins.verlauf5<>del.verlauf5 OR
ins.verlauf6<>del.verlauf6 OR
ins.kurz_sd<>del.kurz_sd;
END;
GO
Problem: mache nichts mit Acces. Ka ob es diese Feldverglecihe (vorher/ nachher) da auch so gibt.
Oder hast du noch Zugriff aut die ERP Quellen? Eine Spalte anfügen geht ja meist. Wenn im SELECT explizit Spalten stehen, fällt die am Ende einfach runter.
Ggf. könnte man so "Modified" Field ncoh einfügen und nur die Tagesdatensätze abgleichen. Das wäre am elegantesten. Mit zusätzlichen Index auf das neue Datumsfeld sollte es dann auch schnell gehen mit dem Abgleich.
Oder hast du noch Zugriff aut die ERP Quellen? Eine Spalte anfügen geht ja meist. Wenn im SELECT explizit Spalten stehen, fällt die am Ende einfach runter.
Ggf. könnte man so "Modified" Field ncoh einfügen und nur die Tagesdatensätze abgleichen. Das wäre am elegantesten. Mit zusätzlichen Index auf das neue Datumsfeld sollte es dann auch schnell gehen mit dem Abgleich.
Hallo Sascha,
was ich jetzt noch nicht so ganz verstanden habe: warum brauchst Du das überhaupt?
Wenn ich von einem alten zu einem neuen System migriere, dann mache ich einen Probelauf bzw. auch mehrere, bis es eben paßt, und dann gibt es einen Zeitpunkt X, zu dem dann der Umzug erfolgt.
Warum willst Du die Daten abgleichen? Willst Du eine Replikation zwischen verschiedenen Systemen einrichten? Nicht wirklich, oder?
Gruß, Mad Max
was ich jetzt noch nicht so ganz verstanden habe: warum brauchst Du das überhaupt?
Wenn ich von einem alten zu einem neuen System migriere, dann mache ich einen Probelauf bzw. auch mehrere, bis es eben paßt, und dann gibt es einen Zeitpunkt X, zu dem dann der Umzug erfolgt.
Warum willst Du die Daten abgleichen? Willst Du eine Replikation zwischen verschiedenen Systemen einrichten? Nicht wirklich, oder?
Gruß, Mad Max
Hallo Sascha,
seit Access 2010 gibt es "event-driven data macro", die kann man wohl als Trigger verwenden. Also kannst Du in alle Tabellen in Access, oder zumindest die großen, zeitkritischen, ein UpdateFlag einfügen, ob was geändert wurde. Das setzt Du per Trigger und setzt es wieder zurück, wenn Du die Daten nach Postgre übertragen hast. Dann brauchst Du immer nur die Daten aktualisieren, die das Flag gesetzt haben.
Problem: gelöschte Zeilen. Entweder das Feststellen der gelöschten Zeilen geht flott genug (delete ... where not exists (...)), oder Du legst statt der Flags in den einzelnen Tabellen eine zusätzliche Tabelle an, wo Du die geänderten Datensätze einträgst.
Aber wenn Du das Update in Postgre flott hinbekommen willst, wirst Du Dir die in Access geänderten Daten merken müssen. Und da Access keinen Datentyp "rowversion" kennt, dürfte das nur über Trigger gehen.
Gruß, Mad Max
seit Access 2010 gibt es "event-driven data macro", die kann man wohl als Trigger verwenden. Also kannst Du in alle Tabellen in Access, oder zumindest die großen, zeitkritischen, ein UpdateFlag einfügen, ob was geändert wurde. Das setzt Du per Trigger und setzt es wieder zurück, wenn Du die Daten nach Postgre übertragen hast. Dann brauchst Du immer nur die Daten aktualisieren, die das Flag gesetzt haben.
Problem: gelöschte Zeilen. Entweder das Feststellen der gelöschten Zeilen geht flott genug (delete ... where not exists (...)), oder Du legst statt der Flags in den einzelnen Tabellen eine zusätzliche Tabelle an, wo Du die geänderten Datensätze einträgst.
Aber wenn Du das Update in Postgre flott hinbekommen willst, wirst Du Dir die in Access geänderten Daten merken müssen. Und da Access keinen Datentyp "rowversion" kennt, dürfte das nur über Trigger gehen.
Gruß, Mad Max
Moin,
für so eine Anwendung würde ich dann den ENTWICKLER für den Migrationspfad fragen. Wenns eh ne hauseigene Entwicklung ist dann sollten die das ja wissen (oder die haben schwachsinnig entwickelt - wenn beides selbst entwickelt wird aber kein Daten migriert werden...).
Als Entwickler hast du ja auch noch andere Möglichkeiten - zum Beispiel einfach die Schreibzugriffe auf die DB einfach auf 2 Datenbanken zu machen.
Wenn du sowas per Hand baust kannst du eben auch ne Menge zerlegen - je nach Grösse und Nutzung des Systems. In der DB gibt es ja ggf. für einige Aktionen Transaktionen - blöd wenn dein Migrationstool die nicht beachtet und danach in der DB unterschiedliche Daten sind. Dann hast du ggf. irgendwelche Auto-Increment werte (z.B. IDs) - wenn du die nicht in der richtigen Reihenfolge überträgst wirds dir dein System auch vor die Füsse werfen.
Von daher würde ich das immer nur über die Applikation migrieren lassen. Und falls irgend möglich z.B. an nem WE die alte DB ausser Funktion setzen, die Daten übertragen und die alte dann auf Read-Only setzen (bzw. in der Applikation dafür sorgen das Save-Buttons abgeschaltet sind). Es ist jetzt nix ungewöhnliches das bei so einer Umstellung eben irgendwann das System mal für 1-2 Tage off ist. Besser so als irgendwann falsche Inhalte oder fehlende Inhalte zu haben.
für so eine Anwendung würde ich dann den ENTWICKLER für den Migrationspfad fragen. Wenns eh ne hauseigene Entwicklung ist dann sollten die das ja wissen (oder die haben schwachsinnig entwickelt - wenn beides selbst entwickelt wird aber kein Daten migriert werden...).
Als Entwickler hast du ja auch noch andere Möglichkeiten - zum Beispiel einfach die Schreibzugriffe auf die DB einfach auf 2 Datenbanken zu machen.
Wenn du sowas per Hand baust kannst du eben auch ne Menge zerlegen - je nach Grösse und Nutzung des Systems. In der DB gibt es ja ggf. für einige Aktionen Transaktionen - blöd wenn dein Migrationstool die nicht beachtet und danach in der DB unterschiedliche Daten sind. Dann hast du ggf. irgendwelche Auto-Increment werte (z.B. IDs) - wenn du die nicht in der richtigen Reihenfolge überträgst wirds dir dein System auch vor die Füsse werfen.
Von daher würde ich das immer nur über die Applikation migrieren lassen. Und falls irgend möglich z.B. an nem WE die alte DB ausser Funktion setzen, die Daten übertragen und die alte dann auf Read-Only setzen (bzw. in der Applikation dafür sorgen das Save-Buttons abgeschaltet sind). Es ist jetzt nix ungewöhnliches das bei so einer Umstellung eben irgendwann das System mal für 1-2 Tage off ist. Besser so als irgendwann falsche Inhalte oder fehlende Inhalte zu haben.
Hallo zusammen,
ich würde hier einem Update- und einem Insert-Trigger arbeiten.
Die Trigger aktualisieren entweder in der eigentlichen Datentabelle zwei neu anzulegende Spalten
inserted_at (BIT)
updated_at (BIT)
Sobal ein neuer Datensatz eingetragen wird wird das Feld inserted_at mit dem aktuellen Timestamp befüllt.
Beim Update erfolgt der Eintrag in das updated_at-Feld.
Anschließend kannst du, je nachdem wie häufig die Daten auf die andere Datenbank transferiert werden sollen die Datensätze übertragen:
Hole neue Datensätze
Select * from MAIN where inserted_at = 1
anschließend
update MAIN set inserted_at = 0 where inserted_at = 1
Hole geänderte Datensätze
delete from ZIEL
WHERE id in (Select id from MAIN where updated_at =1)
Insert into ZIEL ....
Select * from MAIN where updated_at = 1
update MAIN set updated_at = 0 where updated_at = 1
Greetz,
thejoker2305
ich würde hier einem Update- und einem Insert-Trigger arbeiten.
Die Trigger aktualisieren entweder in der eigentlichen Datentabelle zwei neu anzulegende Spalten
inserted_at (BIT)
updated_at (BIT)
Sobal ein neuer Datensatz eingetragen wird wird das Feld inserted_at mit dem aktuellen Timestamp befüllt.
Beim Update erfolgt der Eintrag in das updated_at-Feld.
Anschließend kannst du, je nachdem wie häufig die Daten auf die andere Datenbank transferiert werden sollen die Datensätze übertragen:
Hole neue Datensätze
Select * from MAIN where inserted_at = 1
anschließend
update MAIN set inserted_at = 0 where inserted_at = 1
Hole geänderte Datensätze
delete from ZIEL
WHERE id in (Select id from MAIN where updated_at =1)
Insert into ZIEL ....
Select * from MAIN where updated_at = 1
update MAIN set updated_at = 0 where updated_at = 1
Greetz,
thejoker2305