Kann diese einfache SQL-Abfrage optimiert werden?

7

Ich habe die folgende Frage:

%Vor%
  • in einer Datenbank (1,3 Millionen Adressen, mehr als 4 Millionen Audits)
  • Beide UniqueId-Spalten sind gruppierte Primärschlüssel

Die Abfrage dauert ziemlich lange. Ich bin dumm, aber gibt es einen Weg, es zu optimieren? Ich möchte alle Adresseinträge zählen, die eine zugrunde liegende Audiodatei haben.

BEARBEITEN : alle Ihre Eingaben werden sehr geschätzt, hier sind einige weitere Details:

  • Die Abfrage wird nicht oft ausgeführt (nur zur Validierung), aber danke für den Hinweis zur indizierten Ansicht, ich werde das meines Wissens sicher hinzufügen.
  • Alle Adressen haben eine 1: 1-Prüfung. Nicht alle Audits sind Adressen.
  • Die Abfrage dauert länger als 1 Minute. Ich finde das zu lange für eine einfache Zählung.
ibiza 12.05.2010, 13:15
quelle

8 Antworten

11

Da Sie zwei Datensätze haben, sortiert nach dem gleichen Wert. Haben Sie einen Merge-Join anstelle des Nested-Loop-Joins probiert?

%Vor%

Bearbeiten:

Diese Erklärungen sind konzeptionell. SQL Server führt möglicherweise komplexere Vorgänge durch als meine Beispiele zeigen. Dieses konzeptionelle Verständnis, gepaart mit der Messung von Zeit und logischem IO durch die SET STATISTICS-Befehle und die Untersuchung von Abfrageausführungsplänen, bilden die Grundlage meiner Abfrageoptimierungsmethode (gewachsen über vier Jahre). Möge es Ihnen genauso gut dienen wie mir.

Einrichtung

  • Erhalte 5 Kartendecks.
  • Nehmen Sie 1 Deck und erstellen Sie einen übergeordneten Datensatz.
  • Nimm die anderen 4 Decks und produziere den Child-Datensatz.
  • Bestellen Sie jeden Datensatz nach Kartenwert.
  • Sei m die Anzahl der Karten im übergeordneten Datensatz.
  • Sei n die Anzahl der Karten im Child-Datensatz.

NestedLoop

  • Nehmen Sie eine Karte über den übergeordneten Datensatz.
  • Suche (mit binärer Suche) innerhalb des Child-Datensatzes nach dem ersten Auftreten einer Übereinstimmung.
  • Suchen Sie in der untergeordneten Datenmenge von der ersten Übereinstimmung vorwärts, bis eine Nicht-Übereinstimmung gefunden wird. Du hast jetzt alle Übereinstimmungen gefunden.
  • Wiederholen Sie dies für jede Karte im übergeordneten Datensatz.

Der Nested-Loop-Algorithmus iteriert den übergeordneten Datensatz und durchsucht anschließend den untergeordneten Datensatz einmal für jeden übergeordneten Datenpunkt, wodurch Kosten entstehen: m * log (n)

Zusammenführen

  • Nehmen Sie eine Karte über den übergeordneten Datensatz.
  • Nimm eine Karte vom Anfang des untergeordneten Datensatzes.
  • Wenn die Karten übereinstimmen, ziehe Karten von der Oberseite jedes Decks, bis von beiden keine Übereinstimmung gefunden wird. Produzieren Sie jedes passende Paar zwischen den Eltern- und Kind-Übereinstimmungen.
  • Wenn die Karten nicht übereinstimmen, suchen Sie nach dem kleineren zwischen den Eltern- und den Kinderkarten und ziehen Sie eine Karte über den Datensatz.

Der Merge-Join-Algorithmus iteriert den übergeordneten Datensatz einmal und den untergeordneten Datensatz einmal, wodurch Kosten entstehen: m + n. Es beruht auf den bestellten Daten. Wenn Sie nach einem Merge-Join für nicht georderte Daten fragen, müssen Sie einen Bestellvorgang durchführen. Dies bringt die Kosten zu (m * log (m)) + (n * log (n)) + m + n. Auch das könnte in einigen Fällen besser als eine verschachtelte Schleife sein.

Hash

  • Holen Sie sich einen Kartentisch.
  • Nimm jede Karte aus dem übergeordneten Datensatz und lege sie auf den Kartentisch, wo du sie finden kannst (sie muss nichts mit dem Kartenwert zu tun haben, sondern muss einfach für dich sein).
  • Nimm jede Karte aus dem Kinddatensatz, finde den passenden Elternteil auf dem Kartontisch und produziere das passende Paar.

Der Hash-Join-Algorithmus iteriert einmal den übergeordneten Datensatz und einmal den untergeordneten Datensatz, wodurch Kosten entstehen: m + n. Es beruht auf einer Karten-Tabelle, die groß genug ist, um den gesamten Inhalt des Eltern-Datensatzes aufzunehmen.

    
Amy B 12.05.2010, 15:33
quelle
6

Wenn Sie diese Abfrage häufig ausführen und sehr schnell sein müssen, erstellen Sie eine materialisierte indizierte Sicht darauf. Es wird einen leichten Overhead für INSERT / UPDATE / DELETEs geben, aber diese Abfrage wird fast augenblicklich sein. Die Aggregationen können vorberechnet und im Index gespeichert werden, um teure Berechnungen während der Ausführung der Abfrage zu minimieren.

Verbessern der Leistung bei indizierten SQL Server 2005-Ansichten

    
KM. 12.05.2010 13:22
quelle
2

Das eigentliche Problem ist der Nested-Loop-Join. Für jede 1,4 Millionen Zeilen in der Adresstabelle führen Sie einen Index aus. Suchen Sie in der Tabelle "Auditble" nach. Das bedeutet 1.4M root Block-, Verzweigungsblock- und Leafblock-Lesevorgänge für insgesamt 4.2M Blocklesevorgänge. Der gesamte Index ist wahrscheinlich nur 5K Blöcke oder so ... es sollte einen Hash-Join machen, so dass er beide Indizes einmal liest und durch sie hasht.

Wenn Sie denken, dass diese Tabellen groß sind, denke ich, dass dies auf einer kleinen Box ohne viel Speicher ist. Sie müssen sicherstellen, dass Sie genügend Speicher zugewiesen haben, um den gesamten Index in den Speicher einzupassen, damit der Hash-Join effizient wird.

    
Stephanie Page 12.05.2010 15:18
quelle
1

Ist Auditable.UniqueID ein Fremdschlüsselverweis auf Address.UniqueID, was bedeutet, dass in Auditable keine Werte vorhanden sind, die nicht auch in Address vorhanden sind?

Wenn dies der Fall ist, könnte dies funktionieren und könnte schneller sein:

%Vor%

Hinweis: Dies setzt auch voraus, dass UniqueID eindeutig ist (/ Primärschlüssel) in der Adreßtabelle, aber nicht eindeutig in der Prüftabelle

    
Chris Shaffer 12.05.2010 13:22
quelle
1

Die Klausel EXISTS ist weniger teuer als ein INNER JOIN.

%Vor%

Passt das zu Ihrem Bedürfnis?

N.B. Guids sind sehr teuer für die Datenbank-Engine.

    
Will Marcouiller 12.05.2010 15:25
quelle
0

Nicht sicher, ob es schneller wäre, aber Sie könnten Folgendes versuchen

%Vor%

Es sollte Ihnen die gleiche Anzahl geben, da unqeieieid niemals null sein wird.

    
Ben Robinson 12.05.2010 13:20
quelle
0

Fehlender Index für den Fremdschlüssel, würde ich sagen.

  • 1,4 Millionen und 4 Millionen sind keine großen Tabellen, sie sind klein. Sagen Sie bitte groß, wenn Sie 500 Millionen Einträge durchgehen.

  • Für eine echte Antwort benötigen wir den Ausführungsplan / Abfrageplan, damit wir sehen können, was passiert.

  • Und es wäre schön zu wissen, was "Long" in deiner Welt ist (da du denkst, dass 4 Millionen Zeilen viel sind). Diese Frage wird niemals in 1 Sekunde beantwortet - also was erwartest du und was passiert?

  • Ich wette, Sie haben einen fehlenden Index. Kurz darauf würde ich anfangen, auf die Hardware zu zeigen (weil ich das auch als Grund für Mistleistung gesehen habe).

TomTom 12.05.2010 13:29
quelle
0

Bei großen Tabellen wie diesen möchten Sie möglicherweise Ihre Daten partitionieren, um die Abfrageleistung zu erhöhen. Falls Sie dies noch nicht getan haben, versuchen Sie es mit dem Tuning Advisor, um zu sehen, ob es weitere Indizes gibt, die vorteilhaft sein könnten. Haben Sie kürzlich Ihre Clustered-Indizes neu organisiert - ist das eine Aufgabe, die Teil eines Wartungspakets ist? Viele Male wird dies auch Ihre Leistung stark verbessern.

    
SideFX 12.05.2010 13:31
quelle

Tags und Links