Ich verwende 350GB
auf 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 SSD
Kick-In, wenn die Abfrage startet. Sie wird 20 bis 30 Sekunden lang gelesen und dann 121kB/second
die 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 SELECT
Anweisung ü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
sp_whoisactive
: linkAntworten:
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.
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 :).
quelle
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.
Erstellen Sie einen nicht gruppierten Index für ACALLS.StartTime.
Ändern Sie den Join in ACALLS
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.
quelle