2009-07-07 9 views
8

Ich habe ein interessantes Delimma. Ich habe eine sehr teure Abfrage, bei der mehrere vollständige Tabellen-Scans und teure Joins durchgeführt werden, sowie das Aufrufen einer skalaren UDF, die einige Geodaten berechnet.Mit einer Cache-Tabelle in SQLServer, bin ich verrückt?

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 übernehmen und Gruppen nach Joins und Joins anwenden usw. zur Berechnung der zugehörigen Aggregatdaten.

Lange Rede, kurzer Sinn, um alle Daten, die ich brauche, an die Benutzeroberfläche zu binden, muss diese teure Abfrage etwa 5-6 Mal aufgerufen werden.

Also fing ich an, darüber nachzudenken, wie ich diese teure Abfrage einmal berechnen konnte, und dann konnte 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 Nullable-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.

Dadurch können Sprocs, die an dieser Ergebnismenge arbeiten müssen, eine cacheID von einer vorherigen Abfrage übergeben, und es ist eine einfache SELECT-Anweisung zum Abrufen der Daten (mit einer einzelnen WHERE-Klausel auf der cacheID).

Dann spülen Sie die Cache-Tabelle mit einem periodischen SQL-Job aus.

Dies funktioniert gut und beschleunigt wirklich Dinge auf Zero-Load-Tests. Ich bin jedoch besorgt, dass diese Technik ein Problem unter Last mit großen Mengen von Lese- und Schreibvorgängen gegen die Cache-Tabelle verursachen kann.

Also, lange Geschichte kurz, bin ich verrückt? Oder ist das eine gute Idee?

Offensichtlich muss ich besorgt sein über Sperrkonflikt und Indexfragmentierung, aber alles andere, worüber man sich Sorgen machen sollte?

Antwort

3

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 "nur tun es in der Anwendung" -Lösung, ist, dass viele Zeit haben Sie mehrere Anwendungen mit der DB interagieren, die Sie in eine Bindung setzen können, wenn Sie keine Anwendung Messaging-Bus (oder so ähnlich memcached), weil es teuer sein kann, einen Cache pro Anwendung zu haben.

Offensichtlich ist für Ihr Problem die ideale Lösung, in der Lage zu sein, das Paging in einer preiswerteren Weise zu tun, und nicht ALLE Daten durchlaufen zu müssen, um Seite N zu bekommen. 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.

+0

Dann müsste ich Tausende von Ergebnissen zurück zur App leiten? – FlySwat

+0

Um dies auszuarbeiten, führe ich viele SQL-Operationen mit diesen Daten durch und sende die Ergebnisse einfach an die App. Das Caching in der App wäre kontraproduktiv. – FlySwat

+0

@FlySwat, Ich denke, dass die Einführung eines Vermittlers für diese Überlegung eine Überlegung wert ist. Sie möchten Ihre DB nicht jedes Mal in einen Fit schicken, wenn ein lang laufender Bericht ausgeführt wird. Ein Dienst in der Mitte wird Ihnen die Möglichkeit geben drosseln und die Last auf der DB reduzieren –

1

Ihre tempdb könnte unter Last wie verrückt aufsteigen, also würde ich das sehen. Es ist möglicherweise einfacher, die teuren Joins in eine Ansicht zu stellen und die Ansicht zu indizieren, als zu versuchen, die Tabelle für jeden Benutzer zwischenzuspeichern.

+0

Die Ergebnisse sind sehr willkürlich und basieren auf einer Menge von Eingabeparametern, so dass die Ansicht enorm wäre. Das war auch mein erster Gedanke, aber mir wurde klar, dass die Aussicht Millionen von Reihen benötigen würde. – FlySwat

+1

@FlySway, Millionen von Zeilen ist nicht unbedingt so schlimm. vor allem, wenn Sie am Ende des Tages die Last auf die dB besser verteilen und insgesamt reduzieren. –