Frage

Ich verwende eine Ansicht basierend auf einer komplexen Abfrage mit 17 verbindet (beide inneren und links / rechts außen) und Unterabfragen. All Ansicht Zeilen werden in etwa 5 Sekunden lang angezeigt.

SELECT * FROM a_view;

Eine der Ansicht Spalten Bit-Typ. Und wenn ich Ansicht Reihen filtere es mit 1 zu vergleichen, eine Abfrage funktioniert wieder ca. 5 Sekunden.

SELECT * FROM a_view WHERE c = 1;

Aber wenn ich diese BIT Spalte mit 0 vergleichen, eine Abfrage funktioniert etwa 50 Sekunden (10 mal langsamer).

SELECT * FROM a_view WHERE c = 0;

Diese Abfrage, die die gleichen Ergebniszeilen zurückgibt arbeitet als etwa 10 Sekunden erwartet:

SELECT * FROM a_view 
EXCEPT
SELECT * FROM a_view WHERE c = 1;

So frage ich mich, warum und mit 0 oder ‚falsch‘ zu vergleichen nimmt so viel Zeit? Irgendwelche Ideen, bitte.

Sortierung auf diesem BIT Feld ist schnell. Filterung von anderen Spalten ist schnell zu.

War es hilfreich?

Lösung

Normalerweise gibt es mehr als eine Möglichkeit zum Ausführen einer Abfrage beteiligt verbindet. All moderne RDBMS Suche durch verschiedene Pläne kommt für den besten Plan der Suche nach Kosten (CPU und Plattenzugriffszeiten) für jede Schätzung.

Das Problem ist, jede weitere in einer Join-Abfrage multipliziert die Anzahl der möglichen Pläne durch eine steigende Zahl, die sich in double-faktoriellen (schlechter als exponentiell) Wachstum in der Zahl der Pläne zu prüfen, wie die Anzahl der Joins zunimmt. Aus diesem Grund hat die DB die Suche irgendwo, was bedeutet, suboptimale Pläne unweigerlich für Anfragen bekommen gewählt begrenzen die viele beitritt.

Als Referenz stoppt Auswertung PostgreSQL alle möglichen Pläne nach 12 standardmäßig verbindet. SQL Server wird eine ähnliche Grenze sicher hat. 17 schließt sich nehmen würde (2 * 13) * (2 * 14) * (2 * 15) * (2 * 16) * (2 * 17) mal so lang zu bewerten, - es ist mehr als genug, um jeden RDBMS zu überwältigen, die aufweisen je existiert, oder jemals wird .

Es gibt auch die Tatsache, dass die Kosten DBs Schätzung in einer Spalte und / oder eine Liste der 10 häufigsten Werte in einer Spalte auf Basis von Roh-Statistiken, wie zum Beispiel die Anzahl der unterschiedlichen Werte zu berücksichtigen. Dies alles summiert sich zu der Tatsache, dass, wie die Anzahl der Verknüpfungen nach oben geht, die Wahrscheinlichkeit, dass der beste (oder sogar eine vernünftige) wählen Join-Strategie geht Weg nach unten .

Warum brauchen Sie 17 Tabellen verknüpfen? Gibt es keine Möglichkeit Sie Ihr DB-Schema vereinfachen können?

Andere Tipps

die SQL Server SQL-Engine stellt die gesamte SQL-Abfrage der Ansicht in der SQL-Anweisung, die Sie auf der Ansicht geschrieben und dann versucht, es zu optimieren.

Dies könnte zu einer Situation führen, in denen mit c = 0, die Statistiken der Tabellen zeigen verwendet, dass es viel mehr Zeilen sind dieses Prädikat als mit c = 1 entsprechen. Zum Beispiel mit c = 1, einer Tabelle, die das c-Feld enthält, die das Zentrum der ist schließt sich vielleicht nur 5 passende Zeilen zurück, die zu einem ganz anderen Ausführungsplan führt, als wenn die Tabelle zurückgibt 1 Million Zeilen (was zum Beispiel die Situation für c = 0).

So überprüfen Sie die Ausführungspläne für beide. Überprüfen Sie auch die Server-Profiler Ergebnisse für beide, wie bei c = 0, könnte es sein, es gibt viel mehr liest als mit c = 1, und vieles mehr Ergebnisse als mit c zurückgegeben wird = 1. Wiederkehrende alle Zeilen könnte eine Weile dauern, so auch das der Grund sein könnte, ist die Abfrage langsamer.

Ich weiß, dass dies eine sehr alte Frage, aber wenn jemand noch nach einer Lösung suchen, können Sie versuchen, diese. Ich traf das gleiche Problem vor kurzem, und es war auf einer relativ einfache Abfrage, nur 3 Tabellen in einem Join größten von ihnen mit etwas mehr als 1000 Zeilen. Leider habe ich nicht Privilegien exec Plan zu sehen, also musste ich improvisieren.

select * from subquery_x;

sehr schnell, fertig im Grunde sofort (gerade etwa 500 Zeilen), wie es sollte

select * from subquery_x where column_x = 1  

dtto, sehr schnell, column_x ist eine nicht Null-Bit Spalte

select * from subquery_x where column_x = 0
select * from subquery_x where column_x != 1

sollte etwa 300 Zeilen zurück, die beide sehr, sehr langsam, in der Tat es einige Minuten dauerte !!

einfach (aber komisch) Lösung - wandeln die Spalte in where-Klausel tinyint

select * from subquery_x where convert(tinyint,column_x) = 0

Ich weiß, das könnte einige Leistungsnebenwirkungen hat, aber es funktionierte wie ein Zauber, den Vergleich konvertiert Spaltenwert auf 1 war auch sehr schnell, so lasse ich es so, dass (es wurde in einem Bericht mit dem Vergleichswert verwendet versehen ist, als Parameter)

Wenn jemand weiß, warum dies geschieht, lassen Sie uns wissen, ich vermute, dass es ein Fehler ist, aber wer weiß, könnte genauso gut eine unangenehme Eigenschaft sein: -)

ähnlich wie horcic.roman 's Lösung ... Ich warf den Wert oder Spalte BIT für einen großen Anstieg in der Geschwindigkeit.

myColumn = CAST(1 AS BIT)

CAST(myColumn AS BIT) = 1

Offensichtlich ziemlich seltsam gegeben, dass die Spalte BIT NOT NULL.

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