Die database liest sich bei einer Abfrage mit Indizes drastisch

Ich habe eine Abfrage, die entsprechende Indizes hat und wird im Abfrageplan mit einem geschätzten subtree Kosten von circa 1.5 angezeigt. Der Plan zeigt einen Index Seek, gefolgt von Key Lookup – das ist gut für eine Abfrage erwartet, um 1 Zeile aus einem Satz von 5 bis 20 Zeilen zurückzukehren (dh der Index Seek sollte zwischen 5 und 20 Zeilen und nach 5 – 20 finden Key Lookups, wir sollten 1 Zeile zurückgeben).

Wenn Sie interaktiv laufen, kehrt die Abfrage fast sofort zurück. Allerdings, DB Spuren heute Morgen zeigen Laufzeiten von Live (eine Web-App), die wild variieren; In der Regel nimmt die Abfrage <100 DB Reads und effektiv 0 Laufzeit … aber wir bekommen ein paar Läufe, die> 170.000 DB Reads und Laufzeit bis zu 60s (größer als unser Timeout-Wert) verbrauchen.

Was könnte diese Variation in der Festplatte erklären? Ich habe versucht, Interviews interaktiv zu vergleichen und mit Actual Execution Plänen aus zwei parallelen Läufen mit Filterwerten aus schnellen und langsamen Läufen zu spielen, aber interaktiv zeigen diese effektiv keinen Unterschied im Plan.

Ich habe auch versucht, andere Abfragen zu identifizieren, die dieses Sperren verriegeln könnten, aber ich bin mir nicht sicher, dass das die DB-Lesungen so viel beeinflussen würde … und auf jeden Fall war diese Abfrage eher die schlimmste für die Laufzeit in meinen Trace-Logs.

Update: Hier ist ein Beispiel für den Plan, der bei der interaktiven Abfrage erstellt wird:

Alt-Text

Bitte ignoriere den "fehlenden Index" Text. Es ist wahr, dass Änderungen an den aktuellen Indizes eine schnellere Abfrage mit weniger Lookups ermöglichen könnten, aber das ist hier nicht das Problem (es gibt bereits passende Indizes). Dies ist ein Tatsächlicher Ausführungsplan, wo wir Figuren wie Tatsächliche Anzahl von Zeilen sehen. Zum Beispiel ist bei der Index-search die tatsächliche Anzahl von Zeilen 16, und die I / O-Kosten sind 0,003. Die E / A-Kosten sind bei der Key Lookup gleich.

Update 2: Die Ergebnisse der Trace für diese Abfrage sind:

exec sp_executesql N'select [...column list removed...] from ApplicationStatus where ApplicationGUID = @ApplicationGUID and ApplicationStatusCode = @ApplicationStatusCode;',N'@ApplicationGUID uniqueidentifier,@ApplicationStatusCode bigint',@ApplicationGUID='ECEC33BC-3984-4DA4-A445-C43639BF7853',@ApplicationStatusCode=10 

Die Abfrage wird mit der Gentle.Framework SqlBuilder-class erstellt, die parametrisierte Abfragen wie folgt erstellt:

 SqlBuilder sb = new SqlBuilder(StatementType.Select, typeof(ApplicationStatus)); sb.AddConstraint(Operator.Equals, "ApplicationGUID", guid); sb.AddConstraint(Operator.Equals, "ApplicationStatusCode", 10); SqlStatement stmt = sb.GetStatement(true); IList apps = ObjectFactory.GetCollection(typeof(ApplicationStatus), stmt.Execute()); 

Könnten die data aus dem Cache entfernt werden? Das kann eine Erklärung dafür sein, warum mit einem heißen Cache (data bereits im memory), die gelesenen Aufzeichnungen sind sehr niedrig …. und dann, wenn die data nicht mehr im RAM sind, würden die Lesungen erhöhen, da sie es von der Festplatte lesen muss Nochmals.

Nur eine Idee, die Dinge in Bewegung zu bringen.

Führen Sie Profiler aus, um zu sehen, ob Statistiken um die gleiche time aktualisiert werden. Oder einfach um zu sehen, was sonst noch geht.

Bitte fügen Sie auch die SQL-Abfrage sowie den Client-Code hinzu.

Gedanken:

  • Es klingt wie deine "5-20" Reihen könnte weit mehr sein als das
  • Mit einem schlechten Plan / Parameter schnüffeln Sie bekommen konsequent schlechte performance
  • Wie schreibt man auf diesem Tisch: genug, um Statistiken zu aktualisieren?
  • Gibt es irgendwelche datatypen? (zB Verkettung von Parametern und Einführung einer datatypumwandlung)