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
oder Max Pool Size
?