Zeitstempel-basierter Index


7

Ich habe eine große Datenbank (200 GB +), die einige Protokollinformationen enthält. Und ich möchte SELECTAbfragen und gespeicherte Prozeduren beschleunigen . Ich habe eine Tabelle mit einer GeneratedOnUtc Datums- / Uhrzeitspalte und einen nicht gruppierten Index.

Ich denke daran, es in einen Clustered-Index zu ändern.

Gründe für:

  • Große Datenmenge (~ 40 Millionen Zeilen)

  • Spalte in mehreren verwendet WhereKlauseln ( between, >, <)

  • Die Spalte wird in ROW_NUMBER() OVER (ORDER BY d.GeneratedOnUtc asc) AS RowAbfragen verwendet

Grund gegen:

  • Eine große Anzahl von Einsätzen (~ 60.000 pro Tag) kann zu häufigen Umbauten von B-Bäumen führen.

8
Wenn die eingefügten Daten monoton ansteigen, treten keine "schlechten" Seitenteile auf. Sie können dies sicherstellen, indem Sie die Uhrzeit auf dem Server als Protokolldatum zum Zeitpunkt der Einfügung verwenden.
Max Vernon

1
Hat die Tabelle bereits einen Clustered-Index, den Sie ersetzen würden, oder handelt es sich derzeit um einen Heap? Und wissen Sie ungefähr, wie viel Prozent der Abfragen für diese Tabelle (einschließlich Joins dagegen) das GeneratedOnUtcFeld enthalten würden?
DeadZone

2
@ MaxVernon, aber Sie könnten riskieren, in Latch Contention blogs.msdn.com/b/sqlserverfaq/archive/2010/05/27/…
Tom V - versuchen Sie topanswers.xyz

2
Ein schöner Artikel @TomV, an den ich nie gedacht habe, danke fürs Teilen :) Trotzdem, um SELECTAbfragen und gespeicherte Prozeduren zu beschleunigen, würde ich mich an die Antwort von @ MaxVernon halten. Wenn die 60.000 Einfügungen pro Tag über mehrere Stunden verteilt sind, sollte die Spitze der Einfügungen / Sek. Keine Sorge sein, aber hier habe ich keine Daten. Das Partitionieren der Tabelle könnte ebenfalls von Interesse sein.
JoseTeixeira

1
Ein Clustered-Index für den Zeitstempel ist gut, um die Insert-Leistung zu maximieren. Ich würde mir keine Sorgen über Page Latch-Konflikte machen, wenn die Einfügungsrate nicht bei über 20 KB / s + oder so gehalten wird. Berücksichtigen Sie bei Ihrer Indexstrategie die Leistung ausgewählter Abfragen.
Dan Guzman

Antworten:


4

Das Ändern Ihrer Tabelle von einem Heap zu einem Clustered-Index sollte Ihre Leistung bei beiden Abfragen und möglicherweise sogar bei Einfügungen erheblich verbessern. Im Allgemeinen sollte Ihr Clustered-Index eng, eindeutig und ständig steigend sein. Die Verwendung einer Datums- / Uhrzeitangabe, deren Eindeutigkeit nicht garantiert werden kann, ist nicht ideal, da sie 8 Byte beträgt. Da sie nicht eindeutig ist, fügt SQL nicht eindeutigen Zeilen einen Vier-Byte-Eindeutiger hinzu. Möglicherweise ist es besser, eine Identitätsspalte mit einem int als Clustered-Index zu verwenden, und da dies genau das ist, wonach die "row_number" -Abfragen ohnehin wirklich suchen (eine immer größer werdende eindeutige Zahl), ist dies möglicherweise ein guter Weg, insbesondere wenn Sie einen haben Anzahl der nicht gruppierten Indizes bereits (da der gruppierte Index vom nicht gruppierten als Zeilenzeiger verwendet wird, um ihnen Größe zu verleihen).

Ich schlage vor, Sie erstellen eine Testkopie Ihrer Datenbank und testen sie dann mit einem Clustered-Index für Ihren Datetime-Wert. Vergleichen Sie dies mit einem Test, der einen Clustered-Index für eine neue Identitätsspalte (und einen Nonclustered-Index für Ihre Datetime) verwendet. Sehen Sie, welches mit Ihrer Abfrageladung besser abschneidet. Beide Szenarien übertreffen einen Haufen.


1
Die 4 Bytes werden nur für Zeilen mit identischen Zeitstempeln hinzugefügt. Eine 8-Byte-Datumszeit ändert sich nicht, kann sich ständig erhöhen (wenn sie in der richtigen Reihenfolge eingefügt wird, wie @ MaxVernons Kommentar) und als eng angesehen werden. Ich bin nicht davon überzeugt, dass eine Identität eine bessere Lösung für den jeweiligen Fall ist.
Ypercubeᵀᴹ

1
Danke @ypercube, ich dachte immer, dass der Eindeutiger zu jeder Zeile hinzugefügt wurde, aber einige Grabungen bestätigten, dass Sie Recht haben. Ich habe meine Antwort aktualisiert, um dies widerzuspiegeln. Es ist immer ein guter Tag, wenn Sie neue Dinge lernen. Sie haben vielleicht Recht damit, dass die Identität hier die falsche Lösung ist. Ich glaube, dass die richtige Lösung von der Anzahl und Größe der nicht gruppierten Indizes sowie von den Abfragen abhängt, die Daten lesen. Deshalb habe ich Alex empfohlen, beide Szenarien auszuprobieren.
Ubergeek

Ja, ich stimme Ihrem Vorschlag zu, das Datenvolumen und die Indizes zu testen. 8 Bytes vs 4 können eine große Menge sein, wenn es viele Sekundärindizes gibt. Ich meinte nur, dass, wenn die meisten Abfragen eine Bereichsbedingung mit dem Datum / Uhrzeit haben, es eine geeignete Wahl für das CI sein kann (aber Test, Test, Test, zuerst!)
ypercubeᵀᴹ
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.