{"id":573,"date":"2007-05-18T20:23:20","date_gmt":"2007-05-18T18:23:20","guid":{"rendered":"http:\/\/www.glorf.it\/blog\/2007\/05\/18\/sql-talk\/performance\/trigger-wie-viele-saetze-sind-betroffen"},"modified":"2007-05-18T20:23:20","modified_gmt":"2007-05-18T18:23:20","slug":"trigger-wie-viele-saetze-sind-betroffen","status":"publish","type":"post","link":"http:\/\/www.glorf.it\/blog\/2007\/05\/18\/sql-talk\/performance\/trigger-wie-viele-saetze-sind-betroffen","title":{"rendered":"Trigger &#8211; wie viele S&#228;tze sind betroffen?"},"content":{"rendered":"<p>Gestern las ich bei coreworxx den Artikel &quot;<a href=\"http:\/\/coreworxx.blogspot.com\/2007\/05\/update-trigger-schon-mal-reingefallen.html\">UPDATE Trigger &#8211; schon mal reingefallen?<\/a>&quot; und wollte auch gleich einen Kommentar schreiben. Weil ich dazu aber einen Google-Account einrichten m&#252;sste, antworte ich lieber hier und setze einen Trackback&#8230;<br \/>\nSchade, weil ich jetzt erst mal den Kontext herstellen muss, damit man nicht erst den einen Artikel lesen muss, um diesen zu verstehen. &#220;brigens liebe ich es Artikel &#252;ber SQL-Themen zu lesen: also bitte nicht abschrecken lassen&#8230;<\/p>\n<p>Andreas G&#252;mbel beschreibt in dem Artikel, wie man mittels der Tabellen INSERTED und DELETED mitbekommt wie die Werte des ge&#228;nderten Datensatzes vor und nach der &#196;nderung kommt. Hier eines seiner Beispiele:<\/p>\n<p><code lang=\"sql\">CREATE TRIGGER [TRIGGER_NAME_Update] ON [dbo].[myTableName]<br \/>\nFOR UPDATE<br \/>\nAS<br \/>\nDECLARE @myInsertId int<br \/>\nSELECT @myInsertId=myTableId FROM INSERTED<br \/>\n[weitere Verarbeitung &#8230;]<\/code><\/p>\n<p>Das ist v&#246;llig korrekt beschrieben.<br \/>\nAber dennoch w&#252;rde ich von diesem Statement abraten. Es geht strikt davon aus, dann immer nur ein einziger Datensatz ge&#228;ndert wird. Um die optimale Performance zu erreichen werden in Datenbanksystemen aber immer m&#246;glichst alle betroffenen Datens&#228;tze mit einem Schwupps ge&#228;ndert.<br \/>\nIch merke immer wieder, dass es gerade altgedienten Programmierern schwer f&#228;llt, dass man jetzt nicht mehr m&#252;hsam alles &#252;ber eine Schleife machen muss: In SQL macht man das mit einem einzigen Befehl. Hier mein Lieblingsbeispiel: Alle Mitarbeiter der Datenbankbetreuung bekommen eine 10%ige Gehaltserh&#246;hung&#8230;<\/p>\n<p><code lang=\"sql\">UPDATE Stammdaten.Mitarbeiter<br \/>\n     SET Gehalt = Gehalt * 0.1<br \/>\n     WHERE team=&#x0027;Datenbanktechnologie&#x0027;<\/code><\/p>\n<p>Das Statement dauert fast genau so lange wie der Update eines <em>einzelnen<\/em> Datensatzes.  Deswegen macht man eher selten einen Update auf einen Satz. Und selbst wenn man jetzt fest &#252;berzeugt ist, dass man niemals mehrere S&#228;tze gleichzeitig wird. Sollte man das dennoch vorsehen, weil sich meiner Erfahrung nach sehr schnell die Randbedingungen &#228;ndern und &quot;Puff&quot; knallt der Trigger mitten im laufenden Betrieb an die Wand.<br \/>\nDas ist &#252;brigens eine Tuningma&#223;nahme, die ich immer wieder bei Performanceanalysen empfehlen muss: Mengenupdates anstelle von Schleifen. In der ersten Runde geht es meist auf gar keinen Fall, weil man ja in dem jeweiligen Objekt keine Infos dar&#252;ber hat, welche anderen Objekte sonst noch betroffen sind. Wenn der Druck von Seiten der Kunden steigt, geht es meistens doch&#8230;<\/p>\n<p>Daher: Im Trigger selber bitte immer die Verarbeitung von mehreren Datens&#228;tzen vorsehen.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Gestern las ich bei coreworxx den Artikel &quot;UPDATE Trigger &#8211; schon mal reingefallen?&quot; und wollte auch gleich einen Kommentar schreiben. Weil ich dazu aber einen Google-Account einrichten m&#252;sste, antworte ich lieber hier und setze einen Trackback&#8230; Schade, weil ich jetzt erst mal den Kontext herstellen muss, damit man nicht erst den einen Artikel lesen muss, [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[18],"tags":[],"_links":{"self":[{"href":"http:\/\/www.glorf.it\/blog\/wp-json\/wp\/v2\/posts\/573"}],"collection":[{"href":"http:\/\/www.glorf.it\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/www.glorf.it\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/www.glorf.it\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/www.glorf.it\/blog\/wp-json\/wp\/v2\/comments?post=573"}],"version-history":[{"count":0,"href":"http:\/\/www.glorf.it\/blog\/wp-json\/wp\/v2\/posts\/573\/revisions"}],"wp:attachment":[{"href":"http:\/\/www.glorf.it\/blog\/wp-json\/wp\/v2\/media?parent=573"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.glorf.it\/blog\/wp-json\/wp\/v2\/categories?post=573"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.glorf.it\/blog\/wp-json\/wp\/v2\/tags?post=573"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}