Wir haben eine SQL-Datenbank, in der Anwendungsnutzungsprotokolle für etwa 3000 PCs gespeichert sind. Diese PCs senden ihre Nutzungsdaten etwa 10 bis 20 Mal pro Tag an den SQL Server. Früher haben wir nur die letzten 60 Tage der Anwendungsnutzung gespeichert, aber der Kunde hat uns gebeten, keine Daten mehr zu löschen. Jetzt, da wir Daten im Wert von ungefähr einem Jahr (ungefähr 6.000.000 Zeilen) haben, leidet die SQL-Datenbank unter einigen Leistungsproblemen. Wohlgemerkt nicht signifikant, aber weitaus mehr als jede andere Datenbank, die wir haben. Pro Stunde wird eine erhebliche Anzahl von Datensätzen hinzugefügt ( offene Datensätze für Anwendungen ). Innerhalb weniger Stunden wird dieser Datensatz nur einmal aktualisiert, wenn die zugehörige Anwendung geschlossen wird . Es sind diese Updates, die Sie über SQL Activity Monitor sehen können, deren Fertigstellung viel Zeit in Anspruch nimmt.
Diese UPDATE-Abfrage ist einfach:
SELECT TOP 1 f_ID
from tb_applicationusage
WHERE f_application = 'xxxxxxx' AND
f_computername = 'xxxxxxxxx' AND
f_endtime IS NULL
ORDER BY f_starttime DESC
Tatsächlich wird der letzte übereinstimmende Anwendungsstart für einen bestimmten Computer gefunden, dem noch keine zugeordnete Anwendung geschlossen ist. Ich kann mir keine effizientere Methode zum Ausführen der Abfrage vorstellen. Daher erwäge ich die folgende Alternative:
Wechseln Sie zu zwei Datenbanken:
- Arbeitsdatenbank mit nur den neuesten 24-Stunden-Datensätzen
- Endgültige Datenbank mit allen anderen Datensätzen
Ich bin kein SQL-Guru, daher fehlen mir wahrscheinlich einige Nachteile dieser Methode. Das Ziel wäre, dass ein SQL Agent-Job die abgeschlossenen Datensätze jede Nacht in die endgültige Datenbank verschiebt. Wenn der Kunde dann seine monatlichen Berichte ausführen möchte, kann dieser Bericht nur die endgültige Datenbank und nicht die Arbeitsdatenbank abfragen. Mit nur vielleicht 10.000 Datensätzen, die in der Arbeitsdatenbank abgefragt werden müssen, anstatt 6.000.000, erscheint es logisch, dass es schneller funktionieren würde. Aber auch hier scheint es so einfach zu sein, dass mir wahrscheinlich etwas Offensichtliches fehlt.
Version: Microsoft SQL Server 2008 R2
INDEX
gibt estb_applicationusage
?Antworten:
Sie können es besser machen als zwei Datenbanken. Es gibt zwei Dinge, die Sie in Ihrer vorhandenen Datenbank beachten sollten, bevor Sie einen Teil der alten Daten entfernen.
Wählen Sie einen guten Clustered-Index. Es gibt drei Regeln, die Sie befolgen sollten, damit der Clustered-Index mit diesen Daten gut funktioniert:
Wenn es einen zunehmenden Zeitstempel gibt (dh :)
f_starttime
, kann dies für das erste Feld im Index gut sein, sofern es auch Teil des Abschlussdatensatzes ist, wie in Anforderung 3 angegeben. Fügen Sie weitere Felder hinzu, die Sie benötigen, um einen Datensatz eindeutig oder nahezu eindeutig zu identifizieren. Beachten Sie, dass Sie weiterhin eine Identitätsspalte für die Tabelle verwenden können. Verwenden Sie es einfach nicht als erste Spalte im Clustered-Index. Basierend auf dem SQL-Code in der Frage könnte ich mit gehenf_starttime, f_computername, f_application, f_ID
.Selbst wenn Sie sich für die in der anderen Antwort vorgeschlagene Staging-Tabelle entscheiden, sind diese Indexänderungen möglicherweise immer noch eine gute Idee.
Der andere Vorschlag, ausgefüllte Aufzeichnungen von offenen Aufzeichnungen zu trennen, ist ebenfalls gut. Trotzdem kann die Indizierung und Tabellenpartitionierung hilfreich sein, wenn die Größe der Tabelle für abgeschlossene Datensätze groß wird. Sie können erst dann versuchen, alte Daten in eine separate (verknüpfte) Datenbank zu verschieben, wenn alle diese Optionen fehlgeschlagen sind.
Wirklich, Sql Server ist jedoch leicht in der Lage, sechs Millionen Datensätze zu verarbeiten, ohne auf diese Art von Tricks zurückzugreifen (eine Änderung des Index kann sich jedoch immer noch lohnen). Sind Sie sicher, dass der Server dafür korrekt bereitgestellt ist? Sie können genauso gut einfach RAM zum Server hinzufügen.
Schließlich ist es auch üblich, eine Berichtsdatenbank von der Live-Verarbeitungsdatenbank zu trennen, und es ist überhaupt keine schlechte Sache. Wir nennen dies manchmal ein "Data Warehouse", obwohl dies häufig auch Schemaänderungen und einen SSIS-Prozess zum Verschieben der Daten umfasst. Dies ist eine gute Funktion, da verhindert wird, dass ein versehentlicher Fehler in einer Datenanalyse-Abfrage Leistungsprobleme in der Produktion verursacht. Sie können dies am besten über Datenbankspiegelung / Protokollversand an einen schreibgeschützten Slave oder in jüngerer Zeit über eine AlwaysOn-Verfügbarkeitsgruppe erreichen.
quelle
Zwei Dinge
Sie sagen nicht wirklich, dass Sie einen Index auf dem Tisch haben - ich gehe davon aus, dass dies nur Ihr Problem lösen würde. Ein Index für f_application, f_computername, f_endtime, f_starttime sollte Ihre Aktualisierungszeit mit nur 6 Millionen Datensätzen winzig machen.
Wenn Sie es aufteilen möchten, machen Sie es nicht so, wie Sie es beschreiben. Erstellen Sie eine Tabelle für offene, aber nicht geschlossene Datensätze, die Sie vor Ihrer aktuellen Tabelle verwenden. Wenn dann etwas "aktualisiert" wird, löschen Sie es aus der Staging-Tabelle und fügen Sie es in Ihre große Tabelle ein. Die Verwendung einer Staging-Tabelle auf diese Weise wird als führende / bewährte Methode angesehen. Es ist immer ein Albtraum, wenn eine Tabelle willkürlich in zwei Teile geteilt wird
quelle
Ich denke, ein gefilterter Index würde ganz gut zur Rechnung passen. Basierend auf Ihren Kommentaren zu den anderen Antworten sieht es so aus, als wäre eine Beispielanweisung zum Erstellen eines Index für Sie nützlich. Die Anweisung create index würde ungefähr so aussehen:
Es wäre schön, wenn Sie
UNIQUE
diesen Index einschränken könnten , aber ich bezweifle, dass Sie damit durchkommen können, da immer etwas passieren wird, das ein normales Abmelden / Herunterfahren der Anwendung verhindert. Natürlich sollten Sie (wahrscheinlich ) durch<index name>
einen geeigneten Namen und<schema>
durch das Schema der Tabelle ersetzendbo
. Ich habe dieINCLUDE
Anweisung nur hinzugefügt , weil sie in Ihrer Beispielabfrage enthalten war. Wenn Sie feststellen, dass Sie das nicht brauchen, können Sie es fallen lassen.Ihre Update-Anweisung, wie sie geschrieben wurde, ist kein Update, sondern eine Auswahl. Hier ist ein Beispiel der vollständigen Abfrage, die als Update geschrieben wurde:
Dieses Update hinterlässt natürlich verwaiste Zeilen, die nie abgemeldet wurden. Ich vermute, das ist es, was der monatliche Bericht erkennen soll.
Abschiedsgedanken:
tb_
,f_
wenn möglich. Sie fügen Ihren Objektnamen nur Rauschen hinzu, das das Lesen erschwert und nicht als Best Practice der Branche zu gelten scheint.quelle