2009-08-17 8 views
4

OK. Ich habe hier und da etwas über SQL Server-Heaps gelesen, aber nichts zu definitives, um mich wirklich zu führen. Ich werde versuchen, die Leistung zu messen, hoffe aber auf eine Anleitung, was ich untersuchen sollte. Dies ist SQL Server 2008 Enterprise. Hier sind die Tabellen:Uniqueneidentifier PK: Ist ein SQL Server-Heap die richtige Wahl?

Jobs

  • JobID (PK, GUID, extern erzeugte)
  • Startdate (datetime2)
  • AccountId
  • Mehrere weitere Rechnungslegungs Felder, vor allem Dezimalzahlen und bigints

JobSteps

  • JobStepID (PK, GUID, extern erzeugte)
  • JobID FK
  • Startdatum
  • Mehrere weitere Rechnungslegungs Felder, vor allem Dezimalzahlen und bigints

Verbrauch: Viele Einsätze (Hunderte/Sek.), normalerweise 1 JobStep pro Job. Schätze vielleicht 100-200 Millionen Reihen pro Monat. Es gibt überhaupt keine Updates, und die einzigen Löschungen stammen von Archivierungsdaten, die älter als 3 Monate sind.

Do ~ 10 Abfragen/Sek. Gegen die Daten. Einige treten JobSteps zu Jobs bei, manche schauen sich nur Jobs an. Fast alle Abfragen werden auf StartDate basieren, die meisten von ihnen enthalten AccountId und einige der anderen Accounting-Felder (wir haben Indizes für sie). Abfragen sind ziemlich einfach - der größte Teil der Ausführungspläne ist der Join für JobSteps.

Die Priorität ist die Einfügungsleistung. Einige Verzögerungen (etwa 5 Minuten) sind tolerierbar, damit Daten in den Abfragen angezeigt werden. Daher ist das Replizieren auf andere Server und das Ausführen von Abfragen aus diesen Abfragen zulässig.

Suchen auf der Grundlage der GUIDs ist sehr selten, abgesehen von JobSteps zu Jobs beizutreten.

Aktuelle Konfiguration: Kein Clustered-Index. Der einzige, der wie ein Kandidat aussieht, ist StartDate. Aber es erhöht sich nicht perfekt. Jobs können an einer beliebigen Stelle in einem 3-Stunden-Fenster nach ihrem StartDate eingefügt werden. Das könnte bedeuten, dass eine Million Zeilen in einer Reihenfolge eingefügt werden, die nicht endgültig ist.

Datengröße für einen 1 Job + 1 JobStepId, mit meinen aktuellen Indizes, ist ungefähr 500 Bytes.

Fragen:

  • Ist das eine gute Verwendung eines Haufens?

  • Was ist der Effekt von Clustering auf StartDate, wenn es für ~ 2 Stunden/1 Million Zeilen ziemlich nicht sequenziell ist? Meine Vermutung ist, dass die konstante Nachbestellung die Insert-Perf-Funktion beenden würde.

  • Sollte ich nur bigint PKs hinzufügen, nur um kleinere, immer zunehmende Schlüssel zu haben?(Ich würde immer noch die GUIDs für Lookups müssen.)

ich GUIDs as PRIMARY KEYs and/or the clustering key lesen, und es schien zu vermuten, dass auch einen Schlüssel zu erfinden auf anderen Indizes vielen Platz sparen. Auch einige Ressourcen deuten darauf hin, dass Heaps irgendeine Art von Perf-Problemen im Allgemeinen haben, aber ich bin mir nicht sicher, ob das immer noch in SQL 2008 gilt.

Und wieder, ja, ich werde versuchen zu perf testen und zu messen. Ich versuche nur, einige Anleitungen oder Links zu anderen Artikeln zu bekommen, damit ich eine fundiertere Entscheidung darüber treffen kann, welche Wege in Betracht gezogen werden sollten.

Antwort

5

Ja, haufen haben Probleme. Ihre Daten werden logisch über die gesamte Show verteilt und können nicht einfach defragmentiert werden.

Stellen Sie sich vor, Sie werfen Ihr gesamtes Telefonbuch in einen Eimer und versuchen dann, "Bob Smith" zu finden. Oder Sie verwenden ein herkömmliches Telefonbuch mit einem gruppierten Index für Nachname, Vorname.

Der Verwaltungsaufwand für den Index ist trivial.

StartDate, sofern nicht eindeutig, ist keine gute Wahl. Ein gruppierter Index erfordert interne Eindeutigkeit für die nicht gruppierten Indizes. Wenn nicht eindeutig deklariert, fügt SQL Server ein 4-Byte-"Uniquifier" hinzu.

Ja, ich würde int oder bigint verwenden, um es einfacher zu machen. Wie für GUIDs: Siehe die Fragen auf der rechten Seite des Bildschirms.

Edit:

Hinweis, PK und Clustered-Index sind zwei getrennte Fragen, auch wenn SQL Server-Standard wird die PK gruppierten machen.

+1

Ja, ich wollte auf jeden Fall GUIDs als gruppierten Schlüssel zu vermeiden, da alle anderen Fragen zeigen. StartDate würde eine zusätzliche Identität benötigen. Ich war nur besorgt, dass das Einfügen von im Wesentlichen "zufälligen" Startdaten über einen Zeitraum von 2 Stunden eine Menge Nachbestellung oder etwas anderes bedeuten könnte. Also, kurz gesagt, fügen Sie eine bigint PK hinzu, um alles schön und gruppiert zu bekommen? – MichaelGG

+1

@MichaelGG: ja. es ist schmal, numerisch, streng monoton steigend, unique = gut gruppierter Index – gbn

+0

Richtig, ich verstehe, dass eine int PK viel besser geeignet ist als eine GUID. Meine Frage war, ob ich eine neue Bigint-Spalte hinzufügen sollte, nur um geclusterte Indizes zu haben, anstatt sie als Heap zu verwenden, war eine gute Idee. Es scheint, dass es der richtige Schritt ist. – MichaelGG

1

Da ein GUId Ihr primärer und fremder Schlssel ist, muss Ihre Datenbank immer noch die Randbedingungen auf jeder Einfügung überprüfen, die Sie wahrscheinlich indizieren müssen. Das Indizieren einer GUId ist aufgrund ihrer Zufälligkeit nicht ratsam. Daher würde ich absolut sagen, dass Sie die Bigint (wahrscheinlich Identität) Route für Ihren Primärschlüssel hinuntergehen und sie als einen gruppierten Index verwenden sollten.

+0

Ich brauche immer noch die GUID indiziert, weil ich gelegentlich Lookups darauf machen muss. Ein Nonclustered-Index mit einem niedrigeren Füllfaktor sollte gut funktionieren, nein? – MichaelGG

+0

Ich würde diesen Anruf basierend darauf machen, wie oft Sie Ihre "gelegentlichen" Suchvorgänge durchführen müssen. Wenn du sagst, dass die Insert-Geschwindigkeit der Schlüssel ist, dann helfen weniger Indizes, besonders komplexe wie eine GUId. Wenn Sie eine GUId-Suche pro Woche durchführen, dann ist ein langsamer Tabellen-Scan akzeptabel im Vergleich zur Aufrechterhaltung des Indexes bei 100 Einfügungen pro Sekunde .... Ich schlage vor, dass Sie dies allerdings als Profil verwenden. –

+0

OK - wird tun. Vielen Dank! – MichaelGG

3

Heap-Fragmentierung ist nicht unbedingt das Ende der Welt. Es hört sich so an, als würden Sie die Daten nur selten scannen, also ist das nicht das Ende der Welt.

Ihre nicht gruppierten Indizes sind die Faktoren, die sich auf Ihre Leistung auswirken. Jeder muss die Adresse der Zeile in der Underlynig-Tabelle (entweder einen Heap oder einen gruppierten Index) speichern. Idealerweise müssen Ihre Abfragen niemals die zugrunde liegende Tabelle selbst verwenden, da sie alle benötigten Informationen auf ideale Weise speichert (einschließlich aller Spalten, so dass es sich um einen Deckungsindex handelt).

Und ja, Kimberly Tripps Zeug ist das beste für Indizes.

Rob

+0

Einige der Abfragen sind Aggregate und können nur von einem Index aus bearbeitet werden. Aber viele müssen fast jede einzelne Spalte von beiden Tabellen zurückgeben. Habe ich Kimberlys Informationen verstanden, dass ich durch den Wechsel von guid zu gruppiertem bigint PK viel Platz auf meinen anderen Indizes sparen kann? – MichaelGG

+0

Das Ändern der Struktur (oder eines gruppierten Indexes) wirkt sich auf jeden nicht gruppierten Index in der Tabelle aus. Ich würde vorschlagen, dass das Verlassen Ihrer Daten als Heap der richtige Weg wäre. Verbringen Sie Ihre Zeit damit, Ihre nicht geclusterten Indizes richtig zu machen. Tatsächlich können Sie sogar feststellen, dass nicht gruppierte Indizes mit vielen eingeschlossenen Spalten immer noch besser funktionieren als ein gruppierter Index. Aber ja, ein Bigint (8 Bytes) ist kleiner als eine Guid (16 Bytes), und das erscheint in jeder Leaf-Zeile Ihres NCIX. –

+0

Auch ... Da Sie nicht aktualisieren, sind die größten Unterschiede zwischen dem Verlassen als ein Heap und das Setzen eines Ersatzschlüssels: 1. Einführung eines neuen Feldes wird jede Zeile wachsen, so dass Sie Fragmentierung, die Sie nicht benötigen. 2. Ihre Tabelle muss neu erstellt werden, und die NCIXs damit. 3. Die NCIXs werden etwas kleiner sein, da die 'Zeilenadresse' etwas kleiner geworden ist. Aber am Ende des Tages, holen Sie Ihre NCIXs richtig und Sie sollten sich nicht darum kümmern, wie Ihr zugrunde liegender Heap/CIX aussieht. –

2

Wie Sie Ihre eigene Forschung hat gezeigt, und wie alle anderen Beantworter erwähnt haben, unter Verwendung einer GUID als der Clustered-Index auf einem Tisch ist eine schlechte Idee.

Allerdings ist es nicht wirklich eine gute Wahl, einen Heap zu haben, da Heaps andere Probleme haben, die hauptsächlich mit Fragmentierung und anderen Dingen zu tun haben, die mit einem Heap nicht gut funktionieren.

Mein beste Praxis Rat wäre immer dies sein:

  • tun, um einen primären, gruppierten Schlüssel auf jeder Datentabelle verwenden (es sei denn es eine temporäre Tabelle ist, oder eine Tabelle für Bulk-Laden verwendet)
  • try auch nur um einen guten Clusterindex von - - ich würde argumentieren, dass die Vorteile, die Sie erhalten, indem eine INT/BIGINT Hinzufügen um sicherzustellen, dass eine INT IDENTITY oder BIGINT IDENTITY der gruppierte Schlüssel

ist bei weitem die Nachteile das hat (wie Kim Tripp auch in ihrem Blog po argumentiert) du zitierst).

Marc

Verwandte Themen