Ich habe ein interessantes Delimma. Ich habe eine sehr teure Abfrage, die mehrere vollständige Tabellen-Scans und teure Joins beinhaltet, sowie das Aufrufen einer skalaren UDF, die einige Geodaten berechnet.
Das Endergebnis ist eine Ergebnismenge, die Daten enthält, die dem Benutzer angezeigt werden. Ich kann jedoch nicht alles zurückgeben, was ich dem Benutzer in einem Aufruf zeigen möchte, da ich das ursprüngliche Resultset in Seiten unterteile und nur eine bestimmte Seite zurückgebe. Außerdem muss ich das ursprüngliche gesamte Dataset verwenden und Gruppen nach Joins und Joins anwenden usw., um verwandte Aggregatdaten zu berechnen.
Lange Rede, kurzer Sinn, um alle benötigten Daten an die Benutzeroberfläche zu binden, muss diese teure Abfrage etwa 5-6 mal aufgerufen werden.
Ich begann also darüber nachzudenken, wie ich diese teure Abfrage einmal berechnen könnte, und dann könnte jeder nachfolgende Aufruf irgendwie gegen eine zwischengespeicherte Ergebnismenge ziehen.
Ich kam auf die Idee, die Abfrage in eine gespeicherte Prozedur zu abstrahieren, die eine CacheID (Guid) als nullbaren Parameter aufnehmen würde.
Dieser Sproc würde die Ergebnismenge in eine Cache-Tabelle einfügen, die die cacheID verwendet, um diese spezifische Ergebnismenge eindeutig zu identifizieren.
Dies ermöglicht es Sprocs, die an dieser Ergebnismenge arbeiten müssen, eine cacheID von einer vorherigen Abfrage zu übergeben und es ist eine einfache SELECT-Anweisung, um die Daten (mit einer einzelnen WHERE-Klausel auf der cacheID) abzurufen.
Löschen Sie anschließend die Cache-Tabelle mit einem periodischen SQL-Job.
Das funktioniert super und beschleunigt wirklich die Nulllastprüfung. Ich bin jedoch besorgt, dass diese Technik ein Problem unter Last mit massiven Mengen von Lese- und Schreibvorgängen gegen die Cache-Tabelle verursachen kann.
Also, lange Rede kurzer Sinn, bin ich verrückt? Oder ist das eine gute Idee?
Offensichtlich muss ich mir Sorgen um Sperrkonflikte und Indexfragmentierung machen, aber um alles andere sollte ich mich kümmern?
Ich habe das schon einmal gemacht, vor allem, wenn ich nicht den Luxus hatte, die Anwendung zu bearbeiten. Ich denke, es ist manchmal ein gültiger Ansatz, aber im Allgemeinen wird ein Cache / verteilter Cache in der Anwendung bevorzugt, weil er die Belastung der Datenbank besser reduziert und besser skaliert.
Die knifflige Sache mit der naiven "Just do it in der Anwendung" -Lösung ist, dass Sie oft mehrere Anwendungen mit der DB interagieren, die Sie in eine Bindung bringen können, wenn Sie keinen Anwendungs-Messaging-Bus (oder etwas wie memcached) haben ), weil es teuer sein kann, einen Cache pro Anwendung zu haben.
Offensichtlich ist es für Ihr Problem die ideale Lösung, das Paging kostengünstiger durchzuführen und nicht ALLE Daten abzuarbeiten, nur um Seite N zu erhalten. Aber manchmal ist es nicht möglich. Denken Sie daran, dass das Streaming von Daten aus der Datenbank billiger sein kann als das Streaming von Daten aus der Datenbank zurück in dieselbe Datenbank. Sie könnten einen neuen Dienst einführen, der für die Ausführung dieser langen Abfragen zuständig ist, und dann Ihre Hauptanwendung über den Dienst mit der Datenbank verbinden lassen.
Tags und Links sql-server caching