View Full Version : Durch SQL-Trigger eine 60-fache Laufzeit des betroffenen Progamms.
Achtung: bei ON EACH STATEMENT must du die Daten, die gerade insertet wurden erst wieder lesen, was der Gesamtperformance eher abträglich ist, denn an deinem Insert ändert sich ja nichts.
Das Lesen "from inserted" kommt da noch dazu.
Zusätzlich muss die DB die temporäre "Inserted"-Tabelle schreiben. Also gleich doppelter Performanceverlust.
ON EACH STATEMENT lohnt sich nur, wenn man nicht für jeden Satz eine Operation durchführen muss.
Kodierst du einen einzelnen Insert, wird der Trigger 1x gerufen. Die Daten stehen in "Inserted" als Kopie und nicht in den Programmvariablen.
Kodierst du einen "insert into .... select from..." wird der Trigger wieder 1x aufgerufen.
Auch hier stehen alle Daten noch mal in "Inserted" zur Verfügung.
Das Problem mit dem Datum habe ich auf dem System mit vielen Tabellen, wo ich auch keinen Quellcode für habe. Deshalb diese Funktion.
Andreas Funke
...dieses Detailproblem lässt sich auch mit einer Umsetzungstabelle und Views lösen.
Zentral wäre für mich allerdings zuerst die massive Stundendifferenz zu verstehen, bevor man versucht im nachgelagerten Bereich zu optimieren.
D*B
Ich habe bereits viele Insert/Update-Trigger incl. Update/Inserts korrespondierender Tabellen geschrieben ohne nennenswerte Performanceeinbussen.
Was i.Ü. auch noch gerne vergessen wird:
Zu DDS-Zeiten findet man noch häufig die Angabe FRCRATIO(1) in den PF's. Auch dies kann schon mal die eine oder andere Verzögerung bedeuten (Write-Cache ist abgeschaltet!).
PS:
ON EACH STATEMENT ist i.Ü. der Einzige Trigger bei SQL-Server.
Die kennen nur After-Trigger und Instead-Of.
Den Vorteil von Before-Triggern wollte ich mal diskutieren, das wurde aber überhaupt nicht verstanden.
Die gehen lieber mit "Inserted" und "Deleted" um.
...dieses Detailproblem lässt sich auch mit einer Umsetzungstabelle und Views lösen.
Zentral wäre für mich allerdings zuerst die massive Stundendifferenz zu verstehen, bevor man versucht im nachgelagerten Bereich zu optimieren.
D*B
Danke BenderD,
dass ist das was ich verstehen will.
Warum läuft der Insert über ein select mit Umsetzung des Datums und der Uhrzeit über die Funktion in 16 Minuten durch und der Insert über den Trigger ohne Umsetzung des Datums mit Uhrzeit (also die Funktion wird definitiv nicht aufgerufen) verlängert die Laufzeit des RPG-Programms von 12 Min auf ein Vielfaches.Das Verstehe ich nicht. Wenn wir hier über doppelte Laufzeiten reden würden oder auch die Summe von 12+16Min., also von mir aus 30Minuten, dann wäre das noch nachvollziehbar aber so?
Andreas
Danke BenderD,
dass ist das was ich verstehen will.
Warum läuft der Insert über ein select mit Umsetzung des Datums und der Uhrzeit über die Funktion in 16 Minuten durch und der Insert über den Trigger ohne Umsetzung des Datums mit Uhrzeit (also die Funktion wird definitiv nicht aufgerufen) verlängert die Laufzeit des RPG-Programms von 12 Min auf ein Vielfaches.Das Verstehe ich nicht. Wenn wir hier über doppelte Laufzeiten reden würden oder auch die Summe von 12+16Min., also von mir aus 30Minuten, dann wäre das noch nachvollziehbar aber so?
Andreas
... der Trigger läuft satzweise, der insert select ist eine Bulk Operation, ersteres ohne write cache, zweites mit write cache.
Bulk Operationen sind schnell, aber fatal, wenn das abkackt.
D*B
Ich habe bereits viele Insert/Update-Trigger incl. Update/Inserts korrespondierender Tabellen geschrieben ohne nennenswerte Performanceeinbussen.
Was i.Ü. auch noch gerne vergessen wird:
Zu DDS-Zeiten findet man noch häufig die Angabe FRCRATIO(1) in den PF's. Auch dies kann schon mal die eine oder andere Verzögerung bedeuten (Write-Cache ist abgeschaltet!).
PS:
ON EACH STATEMENT ist i.Ü. der Einzige Trigger bei SQL-Server.
Die kennen nur After-Trigger und Instead-Of.
Den Vorteil von Before-Triggern wollte ich mal diskutieren, das wurde aber überhaupt nicht verstanden.
Die gehen lieber mit "Inserted" und "Deleted" um.
Ja, genau das habe ich auch bisher gemacht. Ich hatte nie nennenswerte Einbussen.
Den Hinweiß auf FRCRATIO(1) werde ich auch noch nachgehen, aber wenn ich die DDS-Datei durch eine SQL-Definierte Tabelle ersetze sollte das ja auch keine Rolle mehr spielen.
Über den Zeitpunkt der Ausführung eines Trigger habe ich mir auch schon öfter den Kopf zerbrochen, habe aber auch noch keine, nicht wiederlegbare, Antwort für befor / after gefunden.
Also wenn ich die Beschreibung richtig interpretiere bedeutet *NONE: Das System verwaltet den Zeitpunkt des Schreibens.
Ja, genau das habe ich auch bisher gemacht. Ich hatte nie nennenswerte Einbussen.
Den Hinweiß auf FRCRATIO(1) werde ich auch noch nachgehen, aber wenn ich die DDS-Datei durch eine SQL-Definierte Tabelle ersetze sollte das ja auch keine Rolle mehr spielen.
Über den Zeitpunkt der Ausführung eines Trigger habe ich mir auch schon öfter den Kopf zerbrochen, habe aber auch noch keine, nicht wiederlegbare, Antwort für befor / after gefunden.
... den Unterschied merkt man bei cascading constraints und wenn man den laufenden update aus dem Trigger heraus modifizieren will.
D*B
Before-Trigger => du hast noch die Chance (falls erlaubt bei externen Triggern) Daten zu manipulieren um Constraints zu befriedigen (setzen Primary Key, Laden Fremdschlüssel, u.ä.)
After-Trigger => wird erst aufgerufen, wenn alle Contraints (Unique Key/Index, Not Null,Check, Ref ...) positiv beschieden sind. Eine Änderung der Daten ist nicht mehr zugelassen.
Beim SQL-Server hat man da eben keine Chance, deshalb wird dort häufig der Einsatz von Prozeduren für Insert/Update empfohlen. Was allerdings nicht unerheblichen Mehraufwand bedeutet und die Unterstützung von EF erschwert.
Wird beim After-trigger dann doch noch ein Update gemacht, wird dann bei tatsächlichen Änderungen des aktuellen Satzes noch die "Satzversionen" für die Transaktionen aktiviert werden.
Häufig wird dann auch noch vergessen, dass ja durchaus mehr als 1 Zeile betroffen wurde.
So, ich habe jetzt auf unsererm Testsystem die Zeit für die Anzahl Sätze pro Stunde aus dem ersten Programmteil (nur Insert der Schlüsselwerte und einer Differenz aus 2 Werten aus der Basisdatei) ermittelt.
- Ohne Trigger werden hier ca. 10,8 Mio Sätze/Stunde eingefügt (6,1 Mio. in 34 Min)
- mit Trigger werden nur 1,5 Mio Sätze/Stunde geschrieben.
Der Insert erfolgt als 1:1 Kopie:
create trigger MIVGES000U after insert on MIVGES00 referencing new as nnn for each row mode db2sql
insert into ANALYSES.ANTRD0000T values(nnn.MGFIRNUM,
nnn.MGKUNNUM,
nnn.MGFILNUM,
nnn.MGVERNUM,
nnn.MGKFZNUM,
nnn.MGKFZART,
nnn.MGKFZGRU,
nnn.MGBERGRU,
nnn.MGUMSGES,
nnn.MGUMS001,
nnn.MGUMS002,
nnn.MGUMS003,
nnn.MGUMS004,
nnn.MGUMS005,
nnn.MGTAGGES,
nnn.MGBERSTD,
nnn.MGDATICO,
nnn.MGTIMICO,
nnn.MGDATICI,
nnn.MGTIMICI,
nnn.MGKILGEF);
label on trigger MIVGES000U is 'Trigger: MIVGES00 insert';
Die Schlüsselwerte sind nnn.MGFIRNUM, nnn.MGKUNNUM, nnn.MGFILNUM.
nnn.MGKILGEF beinhaltet die Differenz vom Kilometerstand checkout und checkin also die gefahrenen Kilometer.
Alle anderen Spalten sind blank oder 0, auch MGDAT* und MGTIM*, Datum und Uhrzeiten sin nummerisch definiert.