Announcement

Collapse
No announcement yet.

Trigger Performance miserabel

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Trigger Performance miserabel

    Hallo,
    Ich habe folgendes problem mit der Performance bei einer DELETE operation:

    Die Operation löscht ca. ein Dutzend Datensätze in der Tabelle "VERSIONS". Diese hat den Primärschlüssel "VersionID". Dann gibt es noch die Tabelle "DEPENDENCIES" in der Abhängigkeiten zwischen den Versionen gespeichert werden und zwar über Fremdschlüsselverweise auf "VERSIONS.VersionID". Hierfür gibt es die Spalten "ParentID" und "ChildID".
    Wenn ein Datensatz aus der Tabelle "VERSIONS" gelöscht wird, sollen logischerweise auch alle Datensätze der Tabelle "DEPENDENCIES" gelöscht werden, die sich auf diese Version beziehen, d.h. bei denen die Version in der Spalte "ParentID" oder "ChildID" eingetragen ist.
    Bei der Fremschlüsseldefinition der Spalte "ParentID" habe ich hierfür die Löschregel "Cascade" angegeben. Leider kann ich nicht dasselbe für die Spalte "ChildID" machen. Dann gibt es immer den Fehler "Multiple Delete Paths", obwohl die beiden IDs nie gleich sein dürfen.
    Deshalb habe ich diese Löschregel über den folgenden Trigger implementiert.

    [highlight=sql]
    USE [Performance\P3]
    GO
    SET ANSI_NULLS ON
    GO
    SET QUOTED_IDENTIFIER ON
    GO
    ALTER TRIGGER [dbo].[T_VERSIONS_DTrig] ON [dbo].[VERSIONS] FOR DELETE AS
    SET NOCOUNT ON

    DELETE DEPENDENCIES FROM deleted, DEPENDENCIES WHERE deleted.VersionID = DEPENDENCIES.ChildID
    [/highlight]

    Das Problem ist nun, dass die Ausführung des Triggers sehr langsam ist. Auf meinem lokalen Rechner werden 5 Sekunden benötigt, auf einem anderen Server im WAN sogar 22 Sekunden, obwohl nur 41 Datensätze betroffen sind.
    Der Server Profiler meldet 7791 Reads und 1800 Writes für die Operation.
    Das seltsame ist: Wenn ich den Befehl "DELETE DEPENDENCIES FROM deleted ...." weglasse, ändert sich daran praktisch nichts. Erst, wenn ich den Trigger ganz lösche, braucht die Operation fast keine Zeit mehr.
    Ich vermute, dass die Zeit damit verplempert wird, die temporäre Tabelle "deleted" anzulegen. In der der Tabelle "VERSIONS" gibt es nämlich eine Spalte mit BLOBs, die auch mal mehrere MB groß sein können.

    Hat jemand eine Idee, ob das der Grund sein kann, oder wie man das ganze schneller kriegt? Gibt es vielleicht eine Möglichkeit das BLOB bei der Operation auszunehmen?
    Was mir auch schleierhaft ist: Warum braucht die Ausführung auf dem anderen Server im WAN so viel länger?
    Zuletzt editiert von Blasterboy; 01.07.2010, 09:03.

  • #2
    Hallo,

    bitte zukünftig beachten: Formatierung von SQL in Beiträgen

    Gruß Falk
    Wenn du denkst du hast alle Bugs gefunden, dann ist das ein Bug in deiner Denksoftware.

    Quellcode ohne ein Mindestmaß an Formatierung sehe ich mir nicht an! Ich leiste keinen Privatsupport per Mail oder PN!

    Comment


    • #3
      Gibt es einen Index auf DEPENDENCIES.ChildID?

      Comment


      • #4
        Ja, Indizes habe ich für alle Primär und Fremdschlüsselspalten erstellt.
        Ich denke auch nicht, dass es daran liegen könnte. Wie beschrieben braucht der Trigger ja genauso lange wenn nur der Befehl SET NOCOUNT ON drin steht und sonst gar nichts gemacht wird

        Comment


        • #5
          Hat niemand eine Idee?

          Comment


          • #6
            Mache von der Tabelle mal eine Kopie aber ohne Blob-Feld(er) und probiere mit der dasselbe nochmal. Wenn's dann schnell geht, kann man die Blob's dazutun und nochmal testen und wenn's immer noch schnell geht ... da weiß ich gerade nichts dazu ...
            Anderenfalls könnte man davon ausgehen, dass es an den Blobs liegt und wenn man schneller werden will, muss man dieses Blobs in eine eigene Tabelle schmeißen und darf nur eine Referenz darauf speichern.

            bye,
            Helmut

            PS: bei Vergleichen lokal mit Server im WAN wurden auch ganz sicher identische Daten(mengen) verwendet

            Comment


            • #7
              Mache von der Tabelle mal eine Kopie aber ohne Blob-Feld(er) und probiere mit der dasselbe nochmal.
              Hab' ich jetzt probiert und hatte keinen nennenswerten Einfluß auf die Performance.

              bei Vergleichen lokal mit Server im WAN wurden auch ganz sicher identische Daten(mengen) verwendet
              Es handelt sich um eine Testdatenbank mit identischem Inhalt. Allerdings habe ich lokal den SQL Server 2008 Developer Edition installiert und auf dem Server läuft noch die 2005er Version. Sollte die so viel langsamer sein.

              Was ich noch festgestellt habe. Wenn ich dieselbe Aktion mehrmals hintereinander durchführe, geht es schneller. Beim ersten Mal werden noch 5s gebraucht, dann 3.5s und später nur noch 1.8s. Im Vergleich dazu braucht eine Access-Datenbank mit denselben Daten nur 0.1s.
              Kann man irgendwie feststellen, wo die Zeit verplempert wird?

              Comment


              • #8
                Am Unterschied Developer Edition 2008 zu einer SQL 2005 Vollversion sollte es nicht liegen, ich habe auch beides im Einsatz und bisher keine nennenswerten Unterschiede in der Performance bemerkt, aber das heisst deswegen nicht, dass es sowas nicht geben kann. Nur als Ursache Nummer 1 würde ich das mal sicher nicht sehen.
                Dass das Ganze anfangs bei jedem Aufruf schneller wird, liegt wohl am SQL-Server, der häufiger benutzte Daten/Tabellen im Hauptspeicher behält.
                Vergleichen mit einer Access-Datenbank kann man dagegen glaube ich vergessen, die hat ja noch nicht mal Trigger. Da ist das Design viel zu unterschiedlich.

                Nachdem meine Vermutung wegen der Blobs wohl falsch war, würde ich als nächstes sicherheitshalber nochmal ein komplette Datenbanksicherung der Echtdaten am Testserver einspielen und auf beiden ein komplettes Index-Reorg über alle Indizes machen (dabei werden die Statistiken automatisch mit upgedatet) und dann den Test nochmal wiederholen.

                bye,
                Helmut

                Comment


                • #9
                  Vergleichen mit einer Access-Datenbank kann man dagegen glaube ich vergessen, die hat ja noch nicht mal Trigger. Da ist das Design viel zu unterschiedlich.
                  Dafür kann ich in Access die DRI Löschweitergabe sowohl zwischen VERSIONS.VersionID und DEPENDENCIES.ParentID als auch zwischen VERSIONS.VersionID und DEPENDENCIES.ChildID setzen. Beim SQL-Server kann ich nur eine setzen.

                  Nachdem meine Vermutung wegen der Blobs wohl falsch war, würde ich als nächstes sicherheitshalber nochmal ein komplette Datenbanksicherung der Echtdaten am Testserver einspielen und auf beiden ein komplettes Index-Reorg über alle Indizes machen (dabei werden die Statistiken automatisch mit upgedatet) und dann den Test nochmal wiederholen.
                  Das hatte ich noch nicht erwähnt: Da die Testdatenbank nur ein paar hundert Datensätze hat, mache ich vor jeder Performancemessung ein Restore, um sicherzugehen, dass ich immer dieselben Ausgangsbedingungen habe.
                  Index-Reorg habe ich ausprobiert: Keine Verbesserung.

                  Comment


                  • #10
                    ... hhmmm, da habe ich jetzt im Moment aber leider auch keine weitere Idee mehr ...
                    Ich hoffe du postest hier das Ergebnis, wenn du den Grund gefunden hast, würde mich echt interessieren.

                    bye,
                    Helmut

                    Comment

                    Working...
                    X