Beste variante um 1-2k Datensätze zu Updaten

Scheffi

Neuer Benutzer
Beiträge
3
Hallo,

Ich bin mit etwas unsicher was das Speichern b.z.w. Updaten von User Daten betrifft.

Ich habe in einen Internal von ca 5 Minuten vor Positionen von Spielern zu Speichern bzw zu aktualisieren.
Zum einen wollte ich vermieden bei 1000 bis 2000 Spielern jeden einzeln alle 5 Minuten zu Speichern. Ich schätze es als nicht sinnvoll ein.


Ein wenig google brachte mich zu 2 Varianten welche mich alle in einem query Unterbringen lässt.

zum einen

UPDATE player SET x CASE WHEN id=1 THEN '0.000' WHEN id=2 THEN '0.000' ..... ELSE x END

Hier sehe ich das Problem das wirklich alles aktualisiert wird auch welche ich nicht Updaten muss

oder


INSERT INTO player (id, x) VALUES (1, '0.000),(2, '0.000) ON DUPLICATE KEY UPDATE x=VALUES(x)

wobei ich bei INSERT INTO bereits feststellen musste das mit auch schon daten verloren gegangen sind da es Einträge gab welche nur x und id enthalten haben, alles andere war leer bzw Default.


Vielleicht könnt ihr mir ja einen Tipp geben was ich bevorzugt machen kann.
 
Werbung:
neu speichern oder aktualisieren?

Wenn nur akualisieren, dann könntest Du einen conditional trigger nehmen, der nur Rows updatet, wenn sich da WIRLICH was ändert. Syntax:

Code:
edb=# \h create trigger
Command:     CREATE TRIGGER
Description: define a new trigger
Syntax:
CREATE [ CONSTRAINT ] TRIGGER name { BEFORE | AFTER | INSTEAD OF } { event [ OR ... ] }
    ON table_name
    [ FROM referenced_table_name ]
    [ NOT DEFERRABLE | [ DEFERRABLE ] [ INITIALLY IMMEDIATE | INITIALLY DEFERRED ] ]
    [ REFERENCING { { OLD | NEW } TABLE [ AS ] transition_relation_name } [ ... ] ]
    [ FOR [ EACH ] { ROW | STATEMENT } ]
    [ WHEN ( condition ) ]
    EXECUTE { FUNCTION | PROCEDURE } function_name ( arguments )

where event can be one of:

    INSERT
    UPDATE [ OF column_name [, ... ] ]
    DELETE
    TRUNCATE

URL: https://www.postgresql.org/docs/13/sql-createtrigger.html

Wichtig ist hier die WHEN ( condition ), hier kannst Du old.* und new.* vergleichen.

Wenn es auch neue Insert's gibt, dann ist die zweite Variante besser. Wenn dabei Daten verloren gehen liegt es wohl an MySQL ...
 
ich nutze Trigger selbst erst seit ein paar Tagen. Verstehe ich das falsch? Ich dachte der Trigger regiert auf Einträge in einer bestimmte Tabelle. Ich hab jetzt nicht ganz verstanden wie ich es aus meiner Cä Anwendung dieses Trigger setzen kann da och doch theoretisch ja eh erst updaten muss damit der trigger was triggern kann oder?
 
TRIGGER reagieren auf Ereignisse. Welche, siehe obige Syntax. Ich weiß nicht, was eine "Cä Anwendung" ist, aber Trigger werden in der Datenbank definiert, nicht in irgend einer Anwendung.
 
cä =D c# Fettfinger!

und das ist das was ich nicht verstehe ^^ Ich lege den trigger in der Datenbank fest, meine c# Anwendung muss ja dann trotzdem Änderungen senden welche der Trigger verarbeitet.

So könnte ich ja gleich alles wie gehabt direkt einschreiben. Oder setze ich den Trigger auf die gleich Tabelle wie die, die ich updaten will und behalte meinen von mir benutzen Update String aus dem Beispiel oben?
 
Werbung:
unverständlich, was Du mir sagen willst. Demo:

Code:
edb=# create table demo(id int primary key, val int);
CREATE TABLE
edb=*# create or replace function check_change() returns trigger as $$begin if new.val = old.val then return null; else return new; end if; end;$$language plpgsql;
CREATE FUNCTION
edb=*# create trigger trg1 before update on demo for each row when (new.val = old.val) execute procedure check_change();
CREATE TRIGGER
edb=*# insert into demo values (1,10);
INSERT 0 1
edb=*# insert into demo values (2,20);
INSERT 0 1
edb=*# select ctid,* from demo;
 ctid  | id | val
-------+----+-----
 (0,1) |  1 |  10
 (0,2) |  2 |  20
(2 rows)

Bis hierhin klar? die ctid ist eine versteckte Spalte, die die physische Position des datensatzes angibt. Jetzt ein Update, welches den val-Wert ändert:

Code:
edb=*# update demo set val = 11 where id = 1;
UPDATE 1
edb=*# select ctid,* from demo;
 ctid  | id | val
-------+----+-----
 (0,2) |  2 |  20
 (0,3) |  1 |  11
(2 rows)

wir haben für id=1 den Wert von val verändert, daher auch eine neu ctid.

Code:
edb=*# update demo set val = 20 where id = 2;
UPDATE 0
edb=*# select ctid,* from demo;
 ctid  | id | val
-------+----+-----
 (0,2) |  2 |  20
 (0,3) |  1 |  11
(2 rows)

edb=*#

hier haben wir für id=2 den selben Wert für val erneut gesetzt. Der Trigger verhindert aber die reale Ausführung des Updates - das spart der DB letztendlich schreibarbeit und, falls eine Replikation im Einsatz ist, Netzwerktraffic.

PS.: die Trigger-Funktion könnte man noch kürzen, die erneute Prüfung auf new.val = old.val ist unnötig, da bereits via when-condition geprüft.
 
Zurück
Oben