Mein Unternehmen verwendet eine Anwendung mit ziemlich großen Leistungsproblemen. Es gibt eine Reihe von Problemen mit der Datenbank selbst, die ich gerade durcharbeite, aber viele der Probleme sind rein anwendungsbezogen.
Bei meiner Untersuchung stellte ich fest, dass Millionen von Abfragen in der SQL Server-Datenbank leere Tabellen abfragen. Wir haben ungefähr 300 leere Tabellen und einige dieser Tabellen werden bis zu 100-200 Mal pro Minute abgefragt. Die Tabellen haben nichts mit unserem Geschäftsbereich zu tun und sind im Wesentlichen Teile der ursprünglichen Anwendung, die der Anbieter nicht entfernt hat, als sie von meinem Unternehmen beauftragt wurden, eine Softwarelösung für uns zu erstellen.
Abgesehen von der Tatsache, dass wir den Verdacht haben, dass unser Anwendungsfehlerprotokoll mit Fehlern im Zusammenhang mit diesem Problem überflutet wird, versichert uns der Anbieter, dass weder für die Anwendung noch für den Datenbankserver Auswirkungen auf die Leistung oder Stabilität bestehen. Das Fehlerprotokoll wird so weit überflutet, dass Fehler im Wert von mehr als 2 Minuten für Diagnosen nicht mehr angezeigt werden.
Die tatsächlichen Kosten dieser Abfragen werden in Bezug auf CPU-Zyklen usw. offensichtlich niedrig sein. Aber kann jemand vorschlagen, wie sich dies auf SQL Server und die Anwendung auswirken würde? Ich würde vermuten, dass die tatsächliche Vorgehensweise beim Senden, Bestätigen, Verarbeiten, Zurücksenden und Bestätigen des Eingangs bei der Bewerbung selbst Auswirkungen auf die Leistung haben würde.
Wir verwenden SQL Server 2008 R2, Oracle Weblogic 11g für die App.
@ Frisbee- Lange Rede, kurzer Sinn, ich habe eine Tabelle mit dem Abfragetext erstellt, der auf die leeren Tabellen in der Datenbank der App traf, und sie dann nach allen Tabellennamen abgefragt, von denen ich weiß, dass sie leer sind, und eine sehr lange Liste erhalten. Der größte Erfolg lag bei 2,7 Millionen Ausführungen über 30 Tage Betriebszeit, wobei zu berücksichtigen ist, dass die App in der Regel von 8 bis 18 Uhr verwendet wird, sodass sich diese Zahlen stärker auf die Betriebsstunden konzentrieren. Mehrere Tabellen, mehrere Abfragen, wahrscheinlich einige über Joins relavent, andere nicht. Der Top-Hit (damals 2,7 Millionen) war eine einfache Auswahl aus einer einzelnen leeren Tabelle mit einer where-Klausel, keine Verknüpfungen. Ich würde erwarten, dass größere Abfragen mit Verknüpfungen zu den leeren Tabellen Aktualisierungen an verknüpften Tabellen enthalten, aber ich werde dies überprüfen und diese Frage so schnell wie möglich aktualisieren.
Update: Es gibt 1000 Abfragen mit einer Ausführungszahl zwischen 1043 und 4622614 (über 2,5 Monate). Ich muss mehr graben, um herauszufinden, wann der zwischengespeicherte Plan stammt. Dies dient nur dazu, Ihnen eine Vorstellung vom Umfang der Abfragen zu geben. Die meisten sind mit mehr als 20 Joins recht komplex.
@ srutzky- ja, ich glaube, es gibt eine Datumsspalte, die sich darauf bezieht, wann der Plan erstellt wurde, damit das von Interesse ist, also werde ich das überprüfen. Ich frage mich, ob Thread-Limits überhaupt ein Faktor sind, wenn sich der SQL Server in einem VMware-Cluster befindet. Zum Glück bald ein dedizierter Dell PE 730xD.
@Frisbee - Entschuldigung für die späte Antwort. Wie Sie vorgeschlagen haben, habe ich mit SQLQueryStress (also tatsächlich 240.000 Iterationen) 10.000 Mal eine Auswahl * aus der leeren Tabelle über 24 Threads ausgeführt und sofort 10.000 Stapelanforderungen / Sek. Erfüllt. Dann habe ich über 24 Threads auf 1000-mal reduziert und knapp 4.000 Batch-Anfragen / Sek. Getroffen. Ich habe auch 10.000 Iterationen über nur 12 Threads versucht (also insgesamt 120000 Iterationen) und dies führte zu anhaltenden 6.505 Batches / Sek. Die Auswirkungen auf die CPU waren tatsächlich spürbar und machten bei jedem Testlauf etwa 5-10% der gesamten CPU-Auslastung aus. Die Netzwerkwartezeiten waren vernachlässigbar (wie 3 ms mit dem Client auf meiner Workstation), aber die Auswirkungen auf die CPU waren mit Sicherheit vorhanden, was für mich ziemlich schlüssig ist. Es scheint auf die CPU-Auslastung und ein bisschen unnötige Datenbankdatei-E / A zurückzuführen zu sein. Die Gesamtausführung / Sekunde liegt bei knapp 3000, Das ist mehr als in der Produktion, aber ich teste nur eine von Dutzenden solcher Abfragen. Der Nettoeffekt von Hunderten von Abfragen, die mit einer Rate zwischen 300 und 4000 Mal pro Minute auf leere Tabellen treffen, wäre daher in Bezug auf die CPU-Zeit nicht vernachlässigbar. Alle Tests wurden gegen einen nicht genutzten PE 730xD mit Dual-Flash-Array und 256 GB RAM sowie 12 modernen Kernen durchgeführt.
@ Srutzky- gutes Denken. SQLQueryStress scheint standardmäßig Verbindungspooling zu verwenden, aber ich habe trotzdem nachgesehen und festgestellt, dass das Kontrollkästchen für Verbindungspooling aktiviert ist. Update folgt
@ srutzky- Das Verbindungspooling ist in der Anwendung anscheinend nicht aktiviert - oder wenn ja, funktioniert es nicht. Ich habe einen Profiler-Trace erstellt und festgestellt, dass die Verbindungen EventSubClass "1 - Nonpooled" für Audit Login-Ereignisse haben.
RE: Verbindungspooling - Überprüfte die Weblogics und stellte fest, dass das Verbindungspooling aktiviert war. Lief mehr Spuren gegen lebende und fand Anzeichen von Pooling, die nicht richtig / überhaupt nicht auftraten:
Und so sieht es aus, wenn ich eine einzelne Abfrage ohne Verknüpfungen für eine aufgefüllte Tabelle ausführe. Die Ausnahmen lauteten "Beim Herstellen einer Verbindung zu SQL Server ist ein netzwerkbezogener oder instanzspezifischer Fehler aufgetreten. Der Server wurde nicht gefunden oder war nicht zugänglich. Stellen Sie sicher, dass der Instanzname korrekt ist und SQL Server so konfiguriert ist, dass Remoteverbindungen zugelassen werden. (Anbieter: Named Pipes Provider, Fehler: 40 - Verbindung zu SQL Server konnte nicht hergestellt werden) "Beachten Sie den Zähler für Stapelanforderungen. Das Pingen des Servers während der Zeit, in der die Ausnahmen generiert werden, führt zu einer erfolgreichen Ping-Antwort.
Update - zwei aufeinanderfolgende Testläufe, gleiche Arbeitslast (wählen Sie * fromEmptyTable), Pooling aktiviert / nicht aktiviert. Etwas mehr CPU-Auslastung und viele Ausfälle und nie mehr als 500 Batch-Anforderungen / Sek. Die Tests zeigen 10.000 Batches / Sek. Und keine Fehler bei aktiviertem Pooling, und ungefähr 400 Batches / Sek. Dann viele Fehler, da das Pooling deaktiviert ist. Ich frage mich, ob diese Fehler auf eine mangelnde Verfügbarkeit der Verbindung zurückzuführen sind.
@ srutzky- Wählen Sie Count (*) aus sys.dm_exec_connections aus.
Pooling aktiviert: 37 konsistent, auch nachdem der Auslastungstest gestoppt wurde
Pooling deaktiviert: 11-37, abhängig davon, ob
in SQLQueryStress Ausnahmen auftreten oder nicht. Wenn diese Täler im
Diagramm "Stapel / Sek." Angezeigt werden, treten die Ausnahmen in SQLQueryStress auf, und die
Anzahl der Verbindungen sinkt auf 11 und wird dann schrittweise auf 37 zurückgesetzt wenn die Chargen ihren Höhepunkt erreichen und die Ausnahmen nicht auftreten. Sehr sehr interessant.
Die maximale Anzahl von Verbindungen auf beiden Test- / Live-Instanzen ist auf den Standardwert 0 festgelegt.
Haben die Anwendungsprotokolle überprüft und können keine Konnektivitätsprobleme feststellen. Aufgrund der großen Anzahl und Größe der Fehler stehen jedoch nur wenige Minuten Protokollierungszeit zur Verfügung, z. B.: Viele Stapelverfolgungsfehler. Ein Kollege für App-Support weist darauf hin, dass im Zusammenhang mit der Konnektivität eine erhebliche Anzahl von HTTP-Fehlern auftritt. Auf dieser Grundlage scheint es, dass die Anwendung aus irgendeinem Grund die Verbindungen nicht korrekt zusammenfasst und dem Server daher wiederholt die Verbindungen ausgehen. Ich werde mehr in App-Protokolle schauen. Ich frage mich, ob es eine Möglichkeit gibt, zu beweisen, dass dies in der Produktion von der SQL Server-Seite aus geschieht.
@ Srutzky- Danke. Ich werde morgen die Weblogic-Konfiguration überprüfen und aktualisieren. Ich habe jedoch über die nur 37 Verbindungen nachgedacht. Wenn SQLQueryStress 12 Threads mit 10.000 Iterationen = 120.000 nicht gepoolten select-Anweisungen ausführt, sollte das nicht bedeuten, dass jede select eine eindeutige Verbindung zur SQL-Instanz erstellt?
@ srutzky- Weblogics sind so konfiguriert, dass sie Verbindungen bündeln, daher sollte es gut funktionieren. Das Verbindungspooling wird in jeder der 4 Weblogics mit Lastenausgleich wie folgt konfiguriert:
- Anfangskapazität: 10
- Maximale Kapazität: 50
- Mindestkapazität: 5
Wenn ich die Anzahl der Threads erhöhe, die die Abfrage "Aus leerer Tabelle auswählen" ausführen, erreicht die Anzahl der Verbindungen einen Spitzenwert von 47. Bei deaktiviertem Verbindungspooling wird durchweg eine niedrigere maximale Stapelanforderung pro Sekunde angezeigt (von 10.000 auf etwa 400). Jedes Mal, wenn die 'Ausnahmen' in SQLQueryStress auftreten, kurz nachdem die Stapel / Sek. In einen Tiefpunkt geraten sind. Es hängt mit der Konnektivität zusammen, aber ich kann nicht genau verstehen, warum dies geschieht. Wenn keine Tests ausgeführt werden, wird #connections auf ca. 12 reduziert.
Wenn das Verbindungspooling deaktiviert ist, habe ich Probleme zu verstehen, warum die Ausnahmen auftreten, aber vielleicht ist es eine ganz andere stackExchange-Frage / Frage für Adam Machanic?
@srutzky Ich frage mich dann, warum die Ausnahmen ohne aktiviertes Pooling auftreten, obwohl dem SQL Server nicht die Verbindungen ausgehen.
SELECT COUNT(*) FROM sys.dm_exec_connections;
ob sich der Wert zwischen aktiviertem Pooling und aktiviertem Pooling stark unterscheidet nicht. Aufgrund dieser Fehler würde es meiner Meinung nach viel mehr Verbindungen geben, wenn das Pooling deaktiviert ist.Pooling=false
oderMax Pool Size
?Antworten:
Ja, und es gibt sogar einige zusätzliche Faktoren, aber das Ausmaß, in dem sich diese tatsächlich auf Ihr System auswirken, lässt sich ohne Analyse des Systems nicht sagen.
That being said, fragen Sie für das, was könnte ein Problem sein, und es gibt einige Dinge zu erwähnen, auch wenn einige von ihnen sind zur Zeit nicht ein Faktor in Ihrer speziellen Situation. Du sagst das:
Es könnte sogar noch mehr geben, aber dies sollte helfen, ein Gefühl für die Dinge zu bekommen. Und denken Sie daran, dass wie bei den meisten Leistungsproblemen alles eine Frage der Skalierbarkeit ist. Alle oben genannten Punkte sind keine Probleme, wenn sie einmal pro Minute getroffen werden. Es ist wie das Testen einer Änderung auf Ihrer Workstation oder in der Entwicklungsdatenbank: Es funktioniert immer mit nur 10 bis 100 Zeilen in den Tabellen. Verschieben Sie diesen Code in die Produktion und die Ausführung dauert 10 Minuten. Jemand muss sagen: "Nun, es funktioniert auf meiner Box" ;-). Das heißt, es liegt nur an der Menge der getätigten Anrufe, dass Sie ein Problem sehen, aber das ist die Situation, die besteht.
Selbst bei 1 Million nutzlosen 0 Zeilenabfragen ergibt sich Folgendes:
Es werden mehr Verbindungen aufrechterhalten, die mehr Speicher beanspruchen. Wie viel unbenutzten physischen RAM haben Sie? Dieser Speicher wird besser zum Ausführen von Abfragen und / oder zum Abfragenplan-Cache verwendet. Im schlimmsten Fall haben Sie nicht mehr genügend physischen Speicher und SQL Server muss den virtuellen Speicher (Swap) verwenden, da dies die Arbeit verlangsamt (überprüfen Sie in Ihrem SQL Server-Fehlerprotokoll, ob Sie Meldungen über ausgelagerten Speicher erhalten).
Und nur für den Fall, dass jemand erwähnt: "Nun, es gibt Verbindungspooling". Ja, das hilft definitiv dabei, die Anzahl der benötigten Verbindungen zu reduzieren. Bei Anfragen, die bis zu 200 Mal pro Minute eingehen, ist dies jedoch eine Menge gleichzeitiger Aktivitäten, und für die legitimen Anforderungen müssen noch Verbindungen bestehen.
SELECT * FROM sys.dm_exec_connections;
Führen Sie a aus, um zu sehen, wie viele aktive Verbindungen Sie pflegen.Wenn ich mich in Bezug auf das, was ich hier angegeben habe, nicht irre, scheint es mir, dass dies eine Art DDoS-Angriff auf Ihr System ist, auch wenn es sich um ein kleines System handelt, da es das Netzwerk und Ihren SQL Server mit falschen Anforderungen überflutet Dadurch wird verhindert, dass echte Anforderungen entweder an SQL Server gelangen oder von SQL Server verarbeitet werden.
quelle
Wenn die Tische 100-200 Mal pro Minute getroffen werden, sind sie (hoffentlich) im Speicher. Die Belastung des Servers ist sehr sehr gering. Sofern Sie nicht über eine hohe CPU oder einen hohen Arbeitsspeicher auf dem Datenbankserver verfügen, ist dies wahrscheinlich kein Problem.
Ja, die Abfragen nehmen gemeinsam genutzte Sperren auf, aber hoffentlich blockieren sie keine Aktualisierungssperren und werden auch nicht durch eine Aktualisierungssperre blockiert. Haben Sie Aktualisierungen, Einfügungen oder Löschungen für diese Tabellen? Wenn nicht, würde ich es einfach loslassen - wenn Sie Leistungsprobleme haben, muss es aus Sicht des Datenbankservers größere Fische zum Braten geben.
Ich habe einen Test mit 100.000 Auswahlzählern (*) für eine leere Tabelle durchgeführt. Er wurde in 32 Sekunden ausgeführt und die Abfragen wurden über ein Netzwerk durchgeführt. Also 1/3 Millisekunde. Sofern Ihr Netzwerk nicht überlastet wird, wirkt sich dies nicht einmal auf den Client aus. Wenn Sie größere Leistungsprobleme haben, sind diese leeren Abfragen von 1/3 Millisekunden nicht das, was die App zum Erliegen bringt.
Und diese können nur Teil eines Links-Joins sein, der einige statische Typdaten abruft, die nicht Teil der aktuellen Anwendung sind. Es könnte mit anderen Abfragen verkettet werden, so dass es keine zusätzliche Rundreise ist. Wenn ja, ist es schlampig, aber es verursacht nicht einmal mehr Verkehr.
Also zurück zu den tatsächlichen Aussagen. Werden in diesen Tabellen Aktualisierungen, Hinzufügungen oder Löschungen angezeigt?
Ja, viele leere Tabellen und Abfragen zu leeren Tabellen weisen auf eine schlampige Codierung hin. Wenn Sie jedoch größere Leistungsprobleme haben, ist dies nicht die Ursache, es sei denn, Sie haben einige wirklich schlampige Schreibvorgänge, die auch mit diesen Tabellen ausgeführt werden.
quelle
Im Allgemeinen werden bei jeder Abfrage die folgenden Schritte ausgeführt:
Viele der von Ihnen erwähnten Abfragen können zu einer zusätzlichen Belastung eines bereits starken Systems führen - eine zusätzliche Belastung für Verbindungen, CPU, RAM und E / A.
quelle