Gibt es eine Möglichkeit, einen Index zu zwingen, mit SQL Server 2008 im Speicher zu bleiben?

10

Ich habe eine Tabelle mit mehreren Millionen Zeilen, aus der ich von Zeit zu Zeit einige Abfragen ausführen muss. Die erste Abfrage ist normalerweise ziemlich langsam (ungefähr 10 Sekunden), und nachfolgende Abfragen sind normalerweise viel schneller (ungefähr 1 Sekunde). Nach einigen Stunden beginnt wieder ein langsamer / dann schneller Zyklus.

Ich habe in meinem Ausführungsplan überprüft, ob alle erforderlichen Indizes vorhanden waren und ordnungsgemäß verwendet wurden, und ich gehe davon aus, dass der Leistungsunterschied auf die Tatsache zurückzuführen ist, dass sich der Index für die nachfolgenden Abfragen tatsächlich im Speicher befindet (habe ich Recht oder gibt es andere mögliche Ursachen?)

Ich führe auch viele andere Abfragen mit Indizes aus, aber diese Abfragen sind weniger zeitaufwändig und ihre Leistung ist weniger kritisch. Daher befürchte ich, dass diese Indizes meinen kritischen Index tatsächlich aus dem Speichercache verschieben.

Abgesehen von dem offensichtlichen Fix "Mehr RAM hinzufügen" habe ich darüber nachgedacht, Dummy-Abfragen zu schreiben, die jede Stunde ausgeführt werden, um den Index wieder in den Speicher zu zwingen.

Gibt es eine elegantere Möglichkeit, dies zu tun? Wie ein Hinweis darauf, dass SQLServer, wenn er nur über genügend Speicher verfügt, um einen einzelnen Index zwischengespeichert zu halten, dieser sein sollte?

Ich weiß, dass es normalerweise am besten ist, SQLServer in Bezug auf diese Art von Dingen nicht durcheinander zu bringen, aber die ungewöhnliche Art meiner Abfrage (die sehr selten, aber zeitkritisch ausgeführt wird) lässt mich glauben, dass sie (wenn möglich) sinnvoll wäre. .

Ich bin auch neugierig zu wissen, ob es eine Möglichkeit gibt zu wissen, welche Indizes zu einem bestimmten Zeitpunkt im Speicher zwischengespeichert werden.

Brann
quelle

Antworten:

13

Früher gab es einen DBCC PINTABLEBefehl, aber ich glaube, dass er in 6.5 oder vielleicht 7.0 nicht mehr funktioniert. Die Aussage wird wahrscheinlich immer noch darauf hinweisen, dass es funktioniert hat, wenn Sie es versuchen, aber es kehrt einfach zurück, es ist wirklich ein No-Op.

Leider gibt es keine Möglichkeit zu steuern, welche Indizes im Cache gespeichert werden. Die beste Problemumgehung, die ich für regelmäßig heiße Tabellen kenne, besteht darin, sie manuell heiß zu halten (was Sie bereits in Ihrer Frage beschrieben haben).

Für welche Indizes sich im Speicher befinden, können Sie sich eine ungefähre Vorstellung machen sys.sm_os_buffer_descriptors. Ich habe einen Tipp dazu veröffentlicht:

http://www.mssqltips.com/sqlservertip/2393/determine-sql-server-memory-use-by-database-and-object/

Aaron Bertrand
quelle
Hmm, laut diesem Skript belegt eine 75-MB-Tabelle 900 MB Pufferpool. Ist das normal / möglich?
DB2
1
@ db2 Wie viele Indizes hast du?
JNK
2
Auch wie fragmentiert ist es ... es misst Seiten, keine Daten. Ihre Seiten sind möglicherweise relativ leer, und dies kann zu einem überhöhten Maß beitragen.
Aaron Bertrand
0

Versuchen Sie, Hinweise zu verwenden KEEPPLANund KEEPPLAN FIXED abzufragen .

KEEPPLAN zwingt den Abfrageoptimierer, den geschätzten Schwellenwert für die Neukompilierung für eine Abfrage zu lockern.

KEEPFIXED PLAN zwingt das Abfrageoptimierungsprogramm, eine Abfrage aufgrund von Änderungen in der Statistik nicht neu zu kompilieren. Durch die Angabe von KEEPFIXED PLAN wird sichergestellt, dass eine Abfrage nur dann neu kompiliert wird, wenn das Schema der zugrunde liegenden Tabellen geändert wird oder wenn sp_recompile für diese Tabellen ausgeführt wird.

Stanley Johns
quelle