Schneidplattenleistung steigt unter Last: Warum?

19

Ich habe ein Stück Code, der Einfügungen in stark denormalisierten Tabellen ausführt. Die Tabellen haben Spaltennummern von ~ 100 bis 300+. Dies ist SQL Server 2008 R2, das unter Windows Server 2008 ausgeführt wird.

Jede Einfügung besteht aus dem Einfügen in eine Reihe von Tabellen unter derselben Transaktion. Einige Einfügungen werden von NHibernate gestapelt, andere jedoch nicht. Sie befinden sich jedoch alle in derselben Transaktion.

Wenn ich zum Beispiel 500-mal Einfügungen durch wiederholtes Aufrufen eines Teils des Codes durchführe, der die Einfügung ausführt, erhalte ich einen Durchschnitt von ~ 360 ms.

Das seltsame Bit ist, wenn ich den Testcode gleichzeitig mit 4 Prozessen ausführe (die gleiche Exe wird von 4 verschiedenen Eingabeaufforderungen unter Windows Server 2008 ausgeführt), wird die Einfügeleistung pro Aufruf viel besser. Ich sehe Bursts, die bis zu 90 ms schnell sind (fast X4 schneller). Ich messe die Einfügezeit aus dem Code.

Da die 4 Prozesse nichts voneinander wissen, gehe ich davon aus, dass dies etwas mit SQL Server zu tun hat, aber ich habe absolut keine Ahnung, warum. Ich würde gerne wissen, warum dies geschieht und ob es eine Konfiguration gibt, die es mir ermöglicht, die gleiche Leistung zu erzielen, wenn die Einfügungen nicht so häufig sind.

Vorschläge zu SQL Server-Überwachungsmethoden, um zu verstehen, was auf Datenbankebene vor sich geht, sind ebenfalls willkommen.

Mahonya
quelle

Antworten:

15

Ein möglicher Grund ist, dass vier gleichzeitige Prozesse ein günstigeres Muster für Protokolllöschvorgänge generieren. Dies bedeutet in der Regel, dass bei jedem Protokolllöschvorgang mehr Daten geschrieben werden, als dies bei einem einzelnen ausgeführten Prozess der Fall ist.

Überwachen Sie Folgendes, um festzustellen, ob der Durchsatz / die Größe des Transaktionsprotokolls ein Faktor ist:

Achten Sie darauf, dass interne Grenzwerte erreicht werden. In SQL Server 2008 R2 können maximal 32 ausstehende (asynchrone) Log-Flush-E / As pro Datenbank in 64-Bit-Versionen (nur 8 in 32-Bit-Versionen) vorhanden sein. Es gibt auch eine maximale Gesamtgröße für die ausstehenden E / A von 3840 KB.

Weitere Informationen und weiterführende Literatur:

Paul White sagt GoFundMonica
quelle
12

Alles, was @PaulWhite sagt, plus ...

Wenn Fremdschlüssel vorhanden sind, muss für jede Einfügung eine Überprüfung für jede referenzierte Tabelle durchgeführt werden. Es hört sich für mich so an, als ob Sie es wären, da Sie nur 360ms bekommen, was sich für mich langsam anfühlt.

Wie auch immer, das Überprüfen dieser Tabellen ist enorm hilfreich, da sich diese Daten bereits im RAM befinden und nicht erst auf die Festplatte geladen werden müssen.

Es klingt für mich so, als ob das Laden der Daten in den RAM ein wichtiger Teil Ihrer Ausführung ist und dass dies nur einmal geschehen muss.

Es könnte auch ein effektives Plan-Caching sein, und Ihre Abfragen müssen beim ersten Mal kompiliert werden, wobei nachfolgende Aufrufe diese Phase vermeiden können.

Rob Farley
quelle
Vielen Dank, Rob. Mein Leistungsproblem hängt mit der hohen Anzahl von Tabellen zusammen, die während eines Einfügens verwendet werden. Es gibt keine Fremdschlüssel. Ich habe sie aus Leistungsgründen entfernt, und meine Modell- und Domänenanforderungen ermöglichen es mir, dies zu tun. Ich lade keine Daten in den Arbeitsspeicher und meine Einfügungen werden dynamisch durch eingehende Anforderungen geformt, die sich ständig ändern. Ich verwende im Grunde genommen ein Star / Snowflake (ish) -Schema für OLTP und versuche, mit der bestmöglichen Leistung davonzukommen.
Mahonya
2
@mahonya, obwohl Sie Daten nicht explizit in den RAM laden, muss SQL Server zuerst die erforderlichen Index- und Datenseiten in den Puffercache lesen, bevor der Einfügevorgang ausgeführt wird. Gleichzeitige Einfügethreads können den Cache erwärmen, sodass ein Thread den Lese-Overhead verursacht und der andere auf die Daten im Cache zugreift.
Dan Guzman
Danke @DanGuzman - und ja, mahonya, es besteht die große Chance, dass dein Cache schön aufgewärmt wird. Ich würde Ihre Wartezeiten überprüfen, um festzustellen, ob es sich um physische E / A handelt, die Ihren Engpass verursachen.
Rob Farley
Thanks @DanGuzman Einverstanden, die Beschleunigung des DB-Index-Caches ist etwas, das ich gewohnt bin, in Postgres zu sehen, die ich wahrscheinlich als Robs Eingabe missverstanden habe.
Mahonya
-3

Einige Server / CPU / OS erinnern sich an die Muster. wie Cache.

Da Sie das Gleiche viermal machen, gibt es bestimmt Möglichkeiten, wie Sie Ecken abschneiden können. Ich vermute, dass Sie es als ersten Weg, als einen langen Prozess (Beispiel 1), aber auf die zweite Art und Weise betrachten Dies sieht den wiederverwendeten Code und führt ihn wie einen Cache aus (Beispiel 2) oder es könnte der erste Prozess sein, der zu groß ist, um alles in den (RAM-Beispiel 3) zu passen.

Beispiel 1: 01111100001101111100001110111000011110111110000

Beispiel 2: 0111110000 | 11 | 0111110000 | 111 | 0111110000 | 1111 | 0111110000

Beispiel 3: 0111110000011111000001111100000111110000 Beispiel 3: Schleife: 0111110000

Ich weiß, Ubuntu Server tut dies mit wiederholten MySQL-Abfragen. Ich kann sie im Cache speichern, obwohl der einzige Unterschied in der Zeit 10-40 mm ist, aber es summiert sich. Als ich in der Schule war, gab es Klassen, die zeigten, dass man Programme (perl / php) dazu bringen muss, diesen Cache schneller zu nutzen.

Aber es kann vom Programm abhängen, welche Sprache es ist, in welcher Sprache es kompiliert ist oder wie es programmiert wurde.

Bryku
quelle