Ich bin nur neugierig, warum eine aggregierte Abfrage mit einer GROUP BY
Klausel so viel schneller ausgeführt wird als ohne.
Die Ausführung dieser Abfrage dauert beispielsweise fast 10 Sekunden
SELECT MIN(CreatedDate)
FROM MyTable
WHERE SomeIndexedValue = 1
Während dieser dauert weniger als eine Sekunde
SELECT MIN(CreatedDate)
FROM MyTable
WHERE SomeIndexedValue = 1
GROUP BY CreatedDate
CreatedDate
In diesem Fall gibt es nur eine , sodass die gruppierte Abfrage dieselben Ergebnisse wie die nicht gruppierte zurückgibt.
Ich habe festgestellt, dass die Ausführungspläne für die beiden Abfragen unterschiedlich sind. Bei der zweiten Abfrage wird Parallelität verwendet, bei der ersten Abfrage nicht.
Ist es normal, dass SQL Server eine aggregierte Abfrage anders auswertet, wenn keine GROUP BY-Klausel vorhanden ist? Und kann ich die Leistung der ersten Abfrage verbessern, ohne eine GROUP BY
Klausel zu verwenden?
Bearbeiten
Ich habe gerade gelernt, dass ich OPTION(querytraceon 8649)
den Kostenaufwand für Parallelität auf 0 setzen kann, wodurch die Abfrage eine gewisse Parallelität verwendet und die Laufzeit auf 2 Sekunden verkürzt wird, obwohl ich nicht weiß, ob die Verwendung dieses Abfragehinweises Nachteile hat.
SELECT MIN(CreatedDate)
FROM MyTable
WHERE SomeIndexedValue = 1
OPTION(querytraceon 8649)
Ich würde immer noch eine kürzere Laufzeit bevorzugen, da die Abfrage einen Wert bei der Benutzerauswahl auffüllen soll und daher im Idealfall wie die gruppierte Abfrage sofort ausgeführt werden sollte. Im Moment bringe ich nur meine Anfrage ein, aber ich weiß, dass das nicht wirklich eine ideale Lösung ist.
SELECT Min(CreatedDate)
FROM
(
SELECT Min(CreatedDate) as CreatedDate
FROM MyTable WITH (NOLOCK)
WHERE SomeIndexedValue = 1
GROUP BY CreatedDate
) as T
Bearbeiten Sie # 2
Als Antwort auf Martins Bitte um weitere Informationen :
Beide CreatedDate
und SomeIndexedValue
haben einen separaten nicht eindeutigen, nicht gruppierten Index. SomeIndexedValue
ist eigentlich ein varchar (7) -Feld, obwohl es einen numerischen Wert speichert, der auf die PK (int) einer anderen Tabelle zeigt. Die Beziehung zwischen den beiden Tabellen ist in der Datenbank nicht definiert. Ich soll die Datenbank überhaupt nicht ändern und kann nur Abfragen schreiben, die Daten abfragen.
MyTable
enthält über 3 Millionen Datensätze, und jedem Datensatz wird eine Gruppe zugewiesen, zu der er gehört ( SomeIndexedValue
). Die Gruppen können zwischen 1 und 200.000 Datensätze umfassen
MAXDOP
Legt den maximalen Grad der Parallelität fest, wodurch die Anzahl der Prozessoren begrenzt wird, die die Abfrage verwenden kann. Dies würde die zweite Abfrage im Grunde so langsam wie die erste ausführen, da dadurch die Parallelität nicht mehr verwendet werden kann. Dies ist nicht das, was ich möchte.Meiner Meinung nach liegt der Grund für das Problem darin, dass der SQL Server-Optimierer nicht nach dem BEST-Plan sucht, sondern nach einem guten Plan, was sich aus der Tatsache ergibt, dass die Abfrage nach dem Erzwingen der Parallelität viel schneller ausgeführt wurde, was der Optimierer hatte nicht alleine gemacht.
Ich habe auch viele Situationen erlebt, in denen das Umschreiben der Abfrage in einem anderen Format den Unterschied zwischen dem Parallelisieren ausmachte (obwohl die meisten Artikel in SQL das Parametrisieren empfehlen, wurde festgestellt, dass es manchmal zu keiner Parallelisierung führt, auch wenn die Parameter nicht identisch sind - Durch Parallelisieren einer oder durch Kombinieren von zwei Abfragen mit UNION ALL kann die Parallelisierung manchmal beseitigt werden.
Als solche könnte die richtige Lösung darin bestehen, verschiedene Arten des Schreibens der Abfrage zu versuchen, z. B. temporäre Tabellen, Tabellenvariablen, cte, abgeleitete Tabellen, Parametrisierung usw., und auch mit den Indizes, indizierten Ansichten oder gefilterten Indizes in zu spielen Um den besten Plan zu bekommen.
quelle