none
Seltsame Performanceprobleme bei Insert mit Select RRS feed

  • Frage

  • Hallo zusammen,

    wir beobachten zur Zeit ein Verhalten des SQL-Servers, dass wir uns nicht erklären können.

    Ein Insertbefehl mit SELECT von derselben Tabelle dauert auf einmal zwischen 3-5 Sekunden. Vor etwa 2 Wochen war der Insert noch im Bereich unter einer Sekunde. Die Datenbanken sind dieselben wie vorher, die Sql-Befehle dieselben. Am Sql-Server hat sich nix verändert, die Hardware ist in ordnung (getestet auf anderen Sql-Servern mit demselben Ergebnis).

    Der Insertbefehl sieht etwa so aus:

    INSERT INTO TABELLE1 (Spalte1, Spalte2, Spalte3 usw)

    SELECT Spalte1, Spalte2, Spalte3 usw

    FROM TABELLE1

    WHERE <Clustered_Index_Spalte> IN (SELECT ZAHL FROM #TMP)


    Interessant sind jetzt folgende Tests:

    - Insert nach Cache löschen dauert etwa 3-5 Sekunden.

    - Führt man den gleichen Insert direkt noch einmal aus, ist die Dauer im Macrosekundenbereich.

    --> Daraus folgt für mich: Das schreiben auf der Festplatte ist nicht das Problem.

    - Löscht man die Nonclustered Indizes von TABELLE1, dauert der INSERT weit unter 1 Sekunde (ohne Cache).

    --> Daraus folgt für mich: Das Problem scheinen die Indizes zu sein (Die Nonclustered Indizes (25 Stück, Varchar oder Int) belegen für diese Tabelle 2,5 GB (ziemlich viel ich weiß, aber leider nötig und vorher auch schon so groß)). 

    - Führt man erst nur den Select aus (ohne Cache) dauert er weit unter 1 Sekunde. Führt man dann den Insert mit Select aus, dauert es 3-5 Sekunden.

    --> Daraus folgt für mich: Der Performancegewinn durch Cache liegt nicht am Lesen oder Suchen der Daten , die geinserted werden sollen.

    --> Daraus folgt für mich: Das Problem scheint das Aktualisieren der Nonclustered Indizes zu sein.

    - Führt man einen Insert aus mit 18 Datensätzen (ungecached) dauert es 3-5 Sekunden, Führt man den Insert noch einmal aus, Macrosekundenbereich, führt man dann den Insert mit 18 anderen Datensätzen aus, dauert es wieder 3-5 Sekunden.

    --> Daraus folgt für mich: Was auch immer da gecached wird, es sind nicht die kompletten Nonclustered Indizes.

    Insgesamt lässt sich danach sagen: Es scheint so zu sein, dass das Laden der Nonclustered Indizes in den Cache das Problem ist. Die Frage ist nur, warum er da nur Teile der Indizes lädt, oder warum er den Cache nicht wieder verwenden kann, wenn andere Daten geinserted werden. Und natürlich die alles entscheidende Frage: Was hat sich geändert, dass es jetzt viel langsamer geworden ist.

    Hat da irgendjemand eine Idee oder kann eine meiner Schlussfolgerungen widerlegen?

    Ich bin da grad ein wenig am verzweifeln.



    Freitag, 17. Februar 2017 13:34

Antworten

  • Wie genau löschst Du eigentlich den Cache?

    Bedenkt, dass ein Abfrageplan genau nur das zeigt: Den Plan wie SQL Server Code eine DML-Operation möchte.

    Was er nicht zeigt, ist, was sonst noch im System passiert und wo das Bottleneck wirklich ist. Sehr dediziert betrachtet ist dies zwar oft im Plan zu sehen, aber in einer produktiven Umgebung passiert weit mehr als der eine Plan.

    Ergo kann man auch ruhig mal Blockaden in Betracht ziehen.

    Daher empfehle ich seit Jahren, auch mal ein komplett andere Perspektive auf Abfragen zu werfen, und zwar die der Ressourcen-Verwendung und Wartevorgänge. Auch bekannt unter der "Wait-Stats" Methodik. Läst sich mittels Extended Events sehr simpel machen.

    Da sieht das Bild oft völig anders aus. Gerade bei Daten aus dem Cache oder auf SSDs, oder eben bei Blockaden.

    Nur mal ein Gedankenanstoß.


    Andreas Wolter (Blog | Twitter)
    MCSM: Microsoft Certified Solutions Master Data Platform/SQL Server 2012
    MCM SQL Server 2008
    MVP Data Platform
    www.SarpedonQualityLab.com | www.andreas-wolter.com

    Montag, 27. Februar 2017 12:01

Alle Antworten

  • Hallo,

    wie viele Spalten hat die Tabelle denn dass man 25 Index braucht. Wenn die Antwort kleiner als 50 ist, sind es eindeutig zu viele Indexe.

    Die Beschreibung klingt so als hättet ihr ein Bookmark Lookup Deadlock Problem. Schaut euch mal das Video hier an und prüft mal ob es eurem Problem entspricht.

    https://www.youtube.com/watch?v=91EZt5y4uiA

    Gruß Benjamin 


    Benjamin Hoch
    MCSE: Data Platform & Data Management and Analytics
    MCSA: SQL Server 2012/2014 & 2016 DB Administration
    MCSA: Windows Server 2012

    Freitag, 17. Februar 2017 16:06
  • Cross Posts sind OK, aber es wäre nett, wenn Du auf diese verweisst, damit man mit lesen kann und sich keiner doppelte Mühe machen muss:

    Strange Performanceproblems with Insert/Select-Statement


    Olaf Helper

    [ Blog] [ Xing] [ MVP]

    Samstag, 18. Februar 2017 07:21
  • Woher kommen Spalte1..3?

    Was ändert sich, wenn Du einen Join formulierst? Geht das überhaupt, oder ist ZAHL kein unique-Feld in #tmp?

    Alternativ mal mit EXISTS probieren! Hast Du auf #tmp einen Index auf ZAHL?

    INSERT INTO TABELLE1 (Spalte1, Spalte2, Spalte3 usw)
    SELECT Spalte1, Spalte2, Spalte3 usw
    FROM TABELLE1 t1
    inner Join #tmp t2
    on t1.<Clustered_Index_Spalte> = t2.ZAHL
    

    Wieviele Zeilen sind in #tmp, wieviele in TABELLE1?

    Wie sieht der Zugriffsplan aus?


    Einen schönen Tag noch, Christoph -- Data Platform MVP - http://www.insidesql.org/blogs/cmu

    Montag, 20. Februar 2017 07:09
  • Hallo,
    ein insert wird durch jeden Index verlangsamt, da für jeden Insert jeder einzelne Index aktualisiert werden muss. Wir machen etwas ähnliches und gehen dabei wie folgt vor:

    Wir droppen sämtliche Indexes. Wir inserten die Datensätze und legen dann erst wieder die Indexes neu auf die Spalten. Das geht insgesamt schneller, und wir ersparen uns die Pflege der Indexes da diese ja immer wieder neu erstellt werden.

    Einfach mal ausprobieren. Am Ergebnis wäre ich sehr interessiert, bitte posten.

    Danke! :-)


    Viele Grüße Holger M. Rößler



    Montag, 20. Februar 2017 09:29
  • Hallo zusammen.

    Vielen Dank für die vielen Antworten.

    Leider scheint keins der genannten Probleme auf meins zuzutreffen.

    Ein "Bookmark Lookup Deadlock" tritt nicht auf, da kein Nonclustered Index durchsucht werden muss für den Select (parallel laufen auch keine anderen Selects (zumindest nicht in der Testumgebung, wo die Probleme auch auftreten).

    Die Nonclustered Indizes zu dropen und neu aufzubauen dauert bei uns mehrere Minuten. Deshalb ist das leider auch keine Option.

    Wir haben 95 Spalten und nur Indizes auf Spalten, nach denen oft gesucht wird.

    Spalte1..3 kommt aus derselben Tabelle, in die wieder geinserted werden soll. Es geht dabei darum, einen "Stand" einzufrieren (also 1 zu 1 Kopie eines Datensatzes, nur der Primärschlüssel unterscheidet sich), auf den man dann aber in gleicher weise selecten können soll wie die normalen Sätze.

    Auf ZAHL in #tmp ist ein Index.

    Join und Exists und ähnliche Konstrukte, die nur den SELECT Befehl ändern, bringen keinen Unterschied

    Den Ausführungsplan darf ich leider noch nicht als Bild hochladen. (96% der Ausführzeit geht für "Clustered Index Insert" drauf. Sonst macht er nur nen Index Scan auf die Tmp-Tabelle und nen Clustered Index Seek auf TABELLE1)


    Montag, 20. Februar 2017 14:17
  • Hallo,
    der "Clustered Index Insert" geht auf die von mir aufgezeigte Problematik zurück. Damit habe ich auch lange gekämpft. Es sollte flotter gehen wenn du die Indexes vor dem inserten runternimmst und danach wieder erzeugst.


    Viele Grüße Holger M. Rößler

    Montag, 20. Februar 2017 15:21
  • Wie genau löschst Du eigentlich den Cache?

    Bedenkt, dass ein Abfrageplan genau nur das zeigt: Den Plan wie SQL Server Code eine DML-Operation möchte.

    Was er nicht zeigt, ist, was sonst noch im System passiert und wo das Bottleneck wirklich ist. Sehr dediziert betrachtet ist dies zwar oft im Plan zu sehen, aber in einer produktiven Umgebung passiert weit mehr als der eine Plan.

    Ergo kann man auch ruhig mal Blockaden in Betracht ziehen.

    Daher empfehle ich seit Jahren, auch mal ein komplett andere Perspektive auf Abfragen zu werfen, und zwar die der Ressourcen-Verwendung und Wartevorgänge. Auch bekannt unter der "Wait-Stats" Methodik. Läst sich mittels Extended Events sehr simpel machen.

    Da sieht das Bild oft völig anders aus. Gerade bei Daten aus dem Cache oder auf SSDs, oder eben bei Blockaden.

    Nur mal ein Gedankenanstoß.


    Andreas Wolter (Blog | Twitter)
    MCSM: Microsoft Certified Solutions Master Data Platform/SQL Server 2012
    MCM SQL Server 2008
    MVP Data Platform
    www.SarpedonQualityLab.com | www.andreas-wolter.com

    Montag, 27. Februar 2017 12:01