SQL Server 2014 Plötzliche Verlangsamung / Keine Einfügungen / Nicht in Bezug auf Hardware oder Index

8

Ich verwende 350GBauf meinem PC eine Datenbank mit ~ 40 Millionen Zeilen.

SQL Server 2014, Win7, AMD 8350 bei 4,8 GHz, 16 GB RAM und eine 500-GB-SSD (die Datenbank wird auf einer eigenen 500-GB-SSD mit einem Durchsatz von 500 MB / 500 MB Lese- / Schreibzugriff gehostet).

Die Datenbank wird nicht aktualisiert, ich analysiere / lese sie nur. Mit der Schaffung von wenigen indexes, jeder join, count(*)usw., dauert weniger als 1 Minute, was für meine Zwecke in Ordnung ist. Ich habe einige Abfragen (nachdem eine einzelne Join-Abfrage 40-50 Mal ausgeführt wurde, wird sie langsam) für die Daten ausgeführt, und jetzt werden Anrufe, die 1 Minute gedauert haben, noch 20 Minuten später ausgeführt.

Ich behalte die Systemressourcen im Auge und sehe den SSDKick-In, wenn die Abfrage startet. Sie wird 20 bis 30 Sekunden lang gelesen und dann 121kB/seconddie nächsten 20 Minuten lang. Dies ist kein CPU- oder Festplattenproblem. Ich bin mit meiner RAM-Größe begrenzt, aber die Aufrufe laufen einwandfrei, als ich die Datenbank zum ersten Mal geladen habe. Jetzt läuft 25 Minuten später nichts mehr.

Tatsächlich kann ich die Datenbank nicht mehr abfragen, jeder Aufruf dauert selbst bei einer grundlegenden SELECTAnweisung übermäßig lange . Ich habe versucht, die Indizes neu zu erstellen und Statistiken zu aktualisieren, aber keinen Unterschied.

Ich habe nicht viel Erfahrung damit, daher ist es durchaus möglich, dass meine SQL-Abfrage falsch ist. In diesem Fall würde ich einen Fehler erwarten oder die Ausführung mit 0 Ergebnissen beenden, aber keines davon tritt auf.

Ich versuche, alle Instanzen einer 'TypeID' in den 5 Sekunden vor einer Zeit zu zählen, die auf der Tabelle ACALLS basiert.

SELECT ACALLS.StartTime, ACALLS.Time, ACALLS.ServerIP, ACALLS.SRVR,   ACALLS.calls, ACALLS.TOKEN, COUNT(TypeID) as ExecRate
FROM ACALLS
INNER JOIN MAINVIEW ON 
MainView.TimeStamp BETWEEN ACALLS.StartTime and DATEADD(ss,-5,ACALLS.StartTime)

WHERE DATEPART(hour,MainView.TimeStamp) BETWEEN 10 and 13 and 
CAST(MainView.TimeStamp as date) = '2015-12-09' and
MainView.TypeID = '123456789'
GROUP BY Acalls.STartTime, ACALLs.TIME, ServerIp,SRVR, ACALLS.CALLS, ACALLS.TOKEN
ORDER BY Acalls.StartTime

Nach dem Ausführen von "Who is Running", Geben Sie hier die Bildbeschreibung ein Geben Sie hier die Bildbeschreibung ein


quelle
Ich vermute, dass dies mit den Statistiken zu den Tabellen und den Verarbeitungsarten für die Joins zu tun hat. Sie sollten sich die Ausführungspläne für die Abfragen ansehen: Verschachtelte Schleifenverknüpfungen können ein Zeichen für Probleme sein.
Gordon Linoff
Haben Sie es mit RECOMPILE versucht?
3
Veröffentlichen Sie einen tatsächlichen Ausführungsplan einer überraschend langsamen Abfrage. Je einfacher die Abfrage, desto besser.
usr
1
Haben Sie die Statistiken für alle Tabellen aktualisiert? Haben Sie alle Indizes neu erstellt? Informationen zu sp_whoisactive: link
TT.
2
Diese Wartestatistiken zeigen viel E / A an, aber wir wissen nicht, welcher Anteil der Abfrage E / A und was CPU ist. Führen Sie die von mir empfohlenen Tests durch, um die Ergebnisse zu veröffentlichen.
usr

Antworten:

2

Sie haben eine nicht SARGable-Abfrage - selbst wenn Sie gute Indizes haben, verwenden Sie diese nicht mit dieser Abfrage.

Erstens liest eine ruckartige Reaktion auf pageiolatch_sh Seiten von der Festplatte in den Puffer; Sie haben nicht genügend RAM für die Daten, die abgerufen werden sollen.

Zweitens müssen Sie sich den Ausführungsplan und seine Verwendung von Indizes ansehen - oder das Fehlen davon.

Beenden Sie die Verwendung von Funktionen in Ihren Joins und Ihrem WHERE und erhalten Sie nur die Daten, mit denen Sie unbedingt beginnen müssen.

  • "ZWISCHEN ACALLS.StartTime und DATEADD (ss, -5, ACALLS.StartTime)" - entfernen Sie dieses DATEADD im ZWISCHEN.

    • Wenn es sich um eine schreibgeschützte Berichtsdatenbank handelt, erstellen Sie eine Berichtstabelle mit nur den benötigten Daten und fügen Sie sie nach Bedarf zusammen. Verwenden Sie diesen, um die Primärschlüssel / anderen eindeutigen Schlüssel der benötigten ACALLS-Zeilen abzurufen, und rufen Sie später den Rest der ACALLS-Daten ab.
  • WHERE DATEPART (Stunde, MainView.TimeStamp) ZWISCHEN 10 und 13 und CAST (MainView.TimeStamp als Datum) = '2015-12-09'

    • Das Gleiche - CAST loswerden - '2015-12-09' in ein oder zwei @ Parameter des richtigen Datentyps für MainView.TimeStamp> = @StartTimestamp AND MainView.TimeStamp <@EndTimestamp ändern

    • und entfernen Sie diesen DATEPART, indem Sie @StartTimestamp und @EndTimestamp so einschränken, dass sie auch Ihre Stundenkriterien enthalten.

Laden Sie möglicherweise eine # temp-Tabelle mit nur den Primär- / Eindeutigkeitsschlüsseln von Zeilen, die diese MainView-Kriterien vor dem Join erfüllen.

Hmm ... auch wenn Mainview eine komplexe Ansicht ist, gehen Sie direkt zu den Basistabellen, um diese # temp-Tabelle zu laden

Vergessen Sie nicht, Profiler zu verwenden, um zu überprüfen, ob das Hinzufügen von (gegebenenfalls zusammengesetzten) Indizes zum #temp oder einer anderen Staging-Tabelle einen Nettogewinn oder einen Nettoverlust darstellt :).

Anti-Schwachkennwörter
quelle
1

Erstellen Sie einen zusammengesetzten nicht gruppierten Index in der Hauptansicht (Typ-ID, Zeitstempel).

Ändern Sie Ihr "Wo" in der Hauptansicht so, dass Sie keine Funktion für die Hauptansichts-Spalten verwenden. Möglicherweise müssen Sie diese Werte vor dem Ausführen der Abfrage als Variablen vorberechnen, wenn diese dynamischer sein sollen.

WHERE MainView.TimeStamp BETWEEN '2015-12-09 10:00' and '2015-12-09 13:00'

Erstellen Sie einen nicht gruppierten Index für ACALLS.StartTime.

Ändern Sie den Join in ACALLS

WHERE ACALLS.StartTime BETWEEN DATEADD(ss,-5,MainView.TimeStamp) AND MainView.TimeStamp

Nach meinem Verständnis wird dies Ihre Logik handhaben und sich mit einer ziemlich hohen Leistung verbinden und Sie von der E / A wegbringen.

Ich gehe davon aus, dass Ihre Daten aus dem Cache gelöscht werden und / oder Tempdb von Zeit zu Zeit auf die Festplatte verschüttet wird. Die beste Lösung, die ich normalerweise gefunden habe, besteht darin, die Abfragen besser zu schreiben Begrenzen Sie die Tempdb- und Speichernutzung und die zugrunde liegenden Probleme verschwinden.

Bruce Dunwiddie
quelle