2017-08-21 1 views
0

Hallo bin ich hoffe, jemand kann meine SQL-Theorie helfen. Ich muss eine Reihe von Berichten erstellen, die Joins aus mehreren Tabellen verwenden. Diese Berichte laufen viel langsamer als ich möchte, und ich hoffe, mein SQL zu optimieren, obwohl mein Wissen eine Wand getroffen hat und ich anscheinend nichts bei Google finde.SQL Mehrere Tabellen Join - Beste Optimierung

Ich hoffe, dass jemand hier mir einige Best Practice Anleitung geben kann.

Im Wesentlichen verbindet Ich versuche, über die Ergebnisse zu filtern gesetzt, wie es

Items INNER JOIN BlueItems ON Items.ItemID = BlueItems.ItemID AND BlueItems.shape = 'square' 
      LEFT JOIN ItemHistory ON Items.ItemID = ItemHistory.ItemsID 
      LEFT JOIN ItemDates ON Items.ItemID = ItemDates.ItemID 
WHERE ItemDates.ManufactureDate BETWEEN '01/01/2017' AND '01/05/2017' 

I reduziert später die Anzahl der Zeilen, die in zurück zu reduzieren kommt auf Blau Artikel herausfinden, dass innerer Füge, die Quadrate sind in beträchtlichem Ausmaß die Daten an diesem Punkt gesetzt?

Ich verstehe auch, dass die Where-Klausel intelligent genug ist, um den Datensatz zur Laufzeit zu reduzieren? Täusche ich mich? Gibt es alle Daten zurück und filtert nur diese Daten?

Jede Anleitung auf im Wesentlichen, wie diese Art der Abfrage zu beschleunigen wäre fantastisch, Index's und solche wurden bereits eingerichtet. Leider wird die Datenbank tatsächlich von jemand anderem verwaltet und ich erstelle einfach Berichte basierend auf ihrer Datenbank. Dies beschränkt mich darauf, nur meine Abfragen und nicht die Daten selbst optimieren zu können.

Ich denke, zu diesem Zeitpunkt ist es Zeit für mich zu versuchen, mein Wissen darüber zu verbessern, wie SQL die verschiedenen Möglichkeiten behandelt, Daten zu filtern und zu verstehen, welche tatsächlich den Datensatz reduzieren und den Filter einfach filtern. Jede Führung wäre sehr willkommen!

+0

'Indexe und dergleichen wurden bereits erstellt '... können Sie uns zeigen, was Sie in Bezug auf die Indexierung getan haben? –

+0

Hallo Tim, diese Seite der Dinge ist nicht in meinem Zuständigkeitsbereich, aber im Wesentlichen kann ich sehen, dass ein Index in den Primärschlüsselfeldern wie allen ItemID Feldern existiert. Leider wird die Datenbank tatsächlich von jemand anderem verwaltet und ich erstelle einfach Berichte basierend auf ihrer Datenbank. Dies beschränkt mich darauf, nur meine Abfragen und nicht die Daten selbst optimieren zu können. – SqlQuery123

Antwort

0

Sie haben erwähnt, dass die Primärschlüssel alle indiziert sind, aber dies ist immer der Fall für Primärschlüsselfelder. Der einzige Teil Ihrer aktuellen Abfrage, der möglicherweise davon profitieren würde, ist der erste Join mit Items. Für die anderen Joins und die WHERE-Klausel werden diese Primärschlüsselfelder nicht verwendet.

Für diese Abfrage würde ich die folgenden Indizes vorschlagen:

ALTER TABLE BlueItems ADD INDEX bi_item_idx (ItemID, shape) 
ALTER TABLE ItemHistory ADD INDEX ih_item_idx (ItemID) 
ALTER TABLE ItemDates ADD INDEX id_idx  (ItemID, ManufactureDate) 

Für die ItemHistory Tabelle, den Index ih_item_idx sollte die ItemID Fremdschlüssel der Verbindung beschleunigen beteiligt sind. Eine Spalte mit dem gleichen Namen ist auch mit den anderen beiden Joins verbunden und gehört somit zu den anderen Indizes. Der Grund für die zusammengesetzten Indizes (d. H. Indizes, die mehr als eine Spalte umfassen) besteht darin, dass wir alle Spalten abdecken wollen, die entweder in der Verknüpfung oder der WHERE-Klausel erscheinen.

+0

Hallo Tim, Danke für den Rat, aber ich denke, ich bin daran interessiert, mehr darüber zu erfahren, wie es auf Abfrageebene funktioniert. Selbst bei optimiertem Indexing frage ich mich, ob die WHERE-Klausel im Allgemeinen besser oder schlechter ist als ein Beitritt und nur die relevanten Daten zu diesem Zeitpunkt enthält. Ich schätze auch, dass ich weiß, wie sich die Anordnung von WHERE auf die Verarbeitung von Daten und dergleichen auswirkt. – SqlQuery123

+0

Sie haben nur eine Bedingung in Ihrer 'WHERE'-Klausel, daher sollte die Bestellung irrelevant sein (und ich denke nicht, dass es im Allgemeinen eine Rolle spielt). Das Vergleichen von "WO" mit einer Verbindung ist Äpfel mit Orangen; Sie sind sehr unterschiedliche Dinge. An dieser Stelle ist das Hinzufügen von Indizes wahrscheinlich die einzige wichtige Verbesserung, die Sie gegenüber Ihrer aktuellen Leistung erzielen können. –

0

Diese Kommentare sind nicht wirklich eine Antwort, aber zu groß, um einen Kommentar zu setzen ...

Wenn die Daten als Parameter übergeben werden (ich vermute, sie sind), dann könnte es sein, Parameter Sniffing das ist verursacht das Problem. Die Abfrage verwendet möglicherweise einen fehlerhaften Plan.

Ich habe das sehr oft gesehen, wenn Sie den Operator between verwenden. Ein paar schnelle Dinge zu versuchen, wie OPTION(RECOMPILE) an das Ende Ihrer Abfrage hinzufügen. Das mag widersprüchlich erscheinen, aber versuchen Sie es einfach. Obwohl kompilierte Abfragen schneller als das erneute Kompilieren sein sollten, kann es, wenn ein fehlerhafter Plan verwendet wird, die Dinge verlangsamen.

Auch, wenn ItemDates groß ist, versuchen Sie, Ihre gefilterten Ergebnisse zu einer temporären Tabelle und damit zu verbinden, so etwas wie.

SELECT * INTO #id FROM ItemDates i WHERE i.ManufactureDate BETWEEN '01/01/2017' AND '01/05/2017' 

Die Änderung, die Sie Haupt-Abfrage so etwas wie

SELECT * 
    FROM Items 
    JOIN BlueItems ON Items.ItemID = BlueItems.ItemID AND BlueItems.shape = 'square' 
    JOIN #id i ON Items.ItemID = i.ItemID 
    LEFT JOIN ItemHistory ON Items.ItemID = ItemHistory.ItemsID 

Ich änderte die sich von einem LEFT JOIN auf eine JOIN (implizit eine innere Verknüpfung) JOIN auch sein, wie Sie nur Elemente ausgewählt werden, die eine haben passen in ItemDates so LEFT Verbindung macht keinen Sinn.