Frage

Ich baue ein paar benutzerdefinierten Berichte für eine SQL Server 2005-Datenbank. Die Datenbank gehört zu einer 3rd-Party-Management-Anwendung, die wir führen. Die Daten, die ich ziehen werde nicht zu dem primären Zweck der Website, so dass die Daten mit Ausnahme der Timestamp-Spalte weitgehend nicht indiziert sind. Vorerst gibt es nur einen Tisch beteiligt - eine Tabelle von rund 700 Millionen Zeilen. Also, wenn ich eine Abfrage es ausführen, die nur 50 Zeilen zurückgeben sollte, hat sie alle 700mil abzufragen.

Ich suche diese zu beschleunigen, aber nicht will, jede Spalte zu indizieren, dass ich zu der WHERE-Klausel bin Hinzufügen - ich weiß nicht, dass fügt hinzu, dass viele Indizes die Geschwindigkeit viel zu verbessern Ende ( oder liege ich falsch?). Also ich bin gespannt, was die beste Praxis wäre, wenn ich konnte nicht alle neuen Indizes in die Tabelle!

Gespeicherte Prozedur scheint nicht wie die beste Passform. Eine indizierte Sicht könnte die beste Idee? Gedanken?

Hier ist das Tabellenschema:

DeviceGuid (PK, uniqueidentifier, not null)
DeviceID (int, not null)
WindowsEventID (PK, int, not null) (indexed)
EventLog (varchar(64), not null)
EventSource (varchar(64), not null)
EventID (int, not null)
Severity (int, not null)
Description (nvarchar(max), not null)
TimeOfEvent (PK, datetime, not null) (indexed)
OccurrenceNbr (int, not null)

Hier ist eine Beispielabfrage:

SELECT COUNT(*) AS NumOcc, EventID, EventLog, EventSource, Severity, TimeOfEvent, Description
FROM WindowsEvent
WHERE DeviceID='34818'
    AND Severity=1
    AND TimeOfEvent >= DATEADD(hh, DATEDIFF(hh, GETDATE(), GETUTCDATE()), '2010/10/27 12:00:00 AM')
    AND TimeOfEvent <= DATEADD(hh, DATEDIFF(hh, GETDATE(), GETUTCDATE()), '2010/11/3 12:00:00 AM')
    AND EventID<>34113
    AND EventID<>34114
    AND EventID<>34112
    AND EventID<>57755
    AND EventSource<>'AutoImportSvc.exe'
    AND EventLog='Application'
GROUP BY EventID, EventLog, EventSource, Severity, Description
ORDER BY NumOcc DESC

Vielleicht ist die Abfrage saugt ... es gibt 53 Zeilen in 4,5 Minuten.

War es hilfreich?

Lösung 3

Die endgültige Lösung war hier eine Abfrage für die indizierten Felder laufen, dann filtern sie innerhalb der Anwendung die Abfrage ausgeführt wird. Zwei Felder am Ende enthält, ähnlich genug Informationen, dass ich gegen einen Index nicht abfragen und erhalten eine sehr enge Annäherung an die Daten, die ich wollte. I zurückgeschleift durch und entfernt jegliche nicht passenden Entitäten aus der Ergebnisliste. Deutlich weniger Zeit benötigt!

Andere Tipps

Wenn Sie Ihre Abfrage keine Indizes verwendet werden es wirklich schlecht sein. Sie haben nicht einen Index für jede Spalte benötigen, aber Sie werden auf der rechten Spalte werden sollen. Da TimeOfEvent bereits indiziert, kann es nicht ein großer für Ihre Bedürfnisse.

Die rechte Spalte wird über die Verteilung Ihrer Daten abhängen. Der beste Index wird wahrscheinlich der Index sein, die höchste Selektivität bereitstellt (das heißt, wenn Sie einen Schlüsselwert für den Index wissen gibt es die wenigsten Zeilen). Wenn Sie die Spalte wissen, dass die beste Selektivität bietet, können Sie den Index auf es versuchen.

Um den besten Index zu ermitteln, können Sie die Anzeige Geschätzten Ausführungsplan in SSMS verwenden. Dies wird Ihnen helfen sehen, welcher Index verwendet wird. Nach dem Hinzufügen eines Index, können Sie Ihre Abfrage ausführen und die Ergebnisse mit dem Ausführungsplan zu bewerten. Und natürlich wird die verstrichene Zeit beobachten können.

versuchen, diese Methode, um die Doppel row_number Trick:

SELECT  RN_Desc as NumOcc, *
FROM    (
        SELECT  row_number() Over(partition by EventId order by EventLog, EventSource, Severity, Description) as RN_Asc,
                row_number() Over(partition by EventId order by EventLog desc, EventSource desc, Severity desc, Description desc) as RN_Desc,
                *
        FROM    WindowsEvent 
        WHERE   DeviceID='34818' 
                AND Severity=1 
                AND TimeOfEvent >= DATEADD(hh, DATEDIFF(hh, GETDATE(), GETUTCDATE()), '2010/10/27 12:00:00 AM') 
                AND TimeOfEvent <= DATEADD(hh, DATEDIFF(hh, GETDATE(), GETUTCDATE()), '2010/11/3 12:00:00 AM') 
                AND EventID<>34113 
                AND EventID<>34114 
                AND EventID<>34112 
                AND EventID<>57755 
                AND EventSource<>'AutoImportSvc.exe' 
                AND EventLog='Application' 
        ) t
WHERE   RN_Asc = 1 
ORDER BY NumOcc DESC 

Mit diesem dem Motor benötigt keine Aggregationen zu tun, nur einen einzigen Durchgang durch den Tisch. wenn es keine Arbeit versucht Spiel mit der Bestellung funktioniert durch und Partition durch Teile der rownumber zu richtigen Gruppierungen zu erhalten.

Das ist ziemlich einfältig, aber ich würde den indizierten Wert als der erste Test in der

versuchen
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top