apollo5891
Goto Top

SQL-Performance mit CTE

Hallo,

ich habe eine SQL-Abfrage mit einer miserablen Performance und würde gerne wissen warum dies so ist.
Eingesetzt wird der SQL Server 2008 R2 (10.50.1600.1) und ich führe die Abfrage über das SQL Server Management Studio aus.
Der eingesetzte Server hat 128 GB RAM.

WITH AllowedProducts As (
SELECT ID FROM tableAllowed (NOLOCK)
WHERE ImportDate BETWEEN '2018-05-20' AND '2018-06-30'
GROUP BY ID
)

SELECT ProductID, ProductName, CustomerID, CustomerName
FROM Cache_Products a (NOLOCK)
INNER JOIN Cache_Customers b (NOLOCK) ON a.ProductID = b.FK_ProductID
AND ProductID IN (
SELECT ID FROM AllowedProducts
)

Die erste Abfrage liefert mir in weniger als 150ms ca. 500 IDs.
Die zweite Abfrage (für die Auswahl der Produkte) benötigt ohne den Filter auf die AllowedProducts 15ms und liefert 40 Ergebnisse.
Wenn die zweite Abfrage aber nun wie oben ausgeführt wird, dann läuft dies ca. 4 Minuten und liefert dann 38 Ergebnisse.

Mich beschäftigt nun die Frage, was dazu führt dazu, dass die Abfrage so langsam ist.
Was passiert dem im SQL-Server, dass zwei Abfragen die einzeln ausgeführt in weniger als 200ms ausgeführt werden, dann so lange brauchen.

Viele Grüße

Content-Key: 376641

Url: https://administrator.de/contentid/376641

Printed on: April 27, 2024 at 20:04 o'clock

Member: em-pie
em-pie Jun 10, 2018 at 16:41:21 (UTC)
Goto Top
Moin,

spontan würde ich sagen, dass die Performance drauf geht, weil du mit jeder ProductID ein SQL-Statement ausführst (so aus dem Bauch heraus).

Versuch doch mal folgendes (ungetestet):
SELECT ProductID, ProductName, CustomerID, CustomerName
FROM Cache_Products a (NOLOCK)
INNER JOIN Cache_Customers b (NOLOCK) ON a.ProductID = b.FK_ProductID
INNER JOIN AllowedProducts as c ON a.ProductID = c.ID

Gruß
em-pie
Member: sabines
sabines Jun 11, 2018 at 05:28:23 (UTC)
Goto Top
Zitat von @Apollo5891:

Eingesetzt wird der SQL Server 2008 R2 (10.50.1600.1) und ich führe die Abfrage über das SQL Server Management Studio aus.
Der eingesetzte Server hat 128 GB RAM.

Moin,

aktuell ist die Version 10.50.6220.0, das erklärt natürlich nicht die Performance, solltest Du allerdings beachten.
Dann wäre die Frage nach Wartungsplänen und auch die Größe der abgefragten Tabellen, ist der Index aktuell und richtig gesetzt.
Was sagt der Profiler und sind die allgemeinen Regeln zur Performance eingehalten.
Hat der Server sonst irgendwelche Auffälligkeiten?

Gruss
Member: ukulele-7
ukulele-7 Jun 11, 2018 at 06:43:43 (UTC)
Goto Top
Grundsätzlich würde ich em-pie zustimmen, lieber einen Join als mit IN vergleichen, das sollte die Performance steigern.

Wieviele Datensätze werden denn im 2ten Select mit dem IN abgeglichen?
Member: GrueneSosseMitSpeck
GrueneSosseMitSpeck Jun 11, 2018 updated at 08:53:50 (UTC)
Goto Top
Also... was theoretisch richtig ist muß praktisch nicht unbedingt die performanteste Lösung sein.

Jede SQL-Server-Version optimiert ein wenig mehr von dem weg, was als suboptimales SQL hingeschrieben wurde wie die Vorherige, und 2008R2 hat da keine gravierenden Performancesceverbesserung gegenüber dem 2008 oder 2005 gehabt... die Optimierungsmöglichkeiten sind aber auch abhängig von der Menge des Arbeitsspeichers. Joins werden z.B. bei Speichermangel in ein select .... where x in (select.... where something... ) umgebaut, deshalb ist ein IN Statement nicht unbedingt falsch.

Man kann
a) das Statement in einem Query-Fenster reinschreiben, und "Abfrage analysieren" ausführen. Grobe Formulierungsfehler bzw. Optimierungen für deine spezifische SQL-Server-Version werden einem dann direkt angezeigt, genauso halbwegs realistische Empfehlungen über Indizes oder Statistiken.

b) den Database tuning advisor starten - er tracet die Datenbank für einen gewissen Zeitraum, und man muß Abfragen ausführen, die der Tuning Advisor dann findet. Das sollte "kalt" passieren, so daß der Server sich die Daten oder Statistiken nicht aus dem RAM holt, was bei wiederholter Ausführung verfälschte Ergebnisse produziert. Nachdem das passiert ist, gibt es eine Auflisitung an Statistiken, Indizes und generellen Empfehlungen.

Generell sind Datumsvergleiche teuer, wenn die Spalte etwas anderes als als ein Timestamp Datentyp ist. Oft wird ein Datum im Textformat reingeschrieben und später bei einem "between" mit einer Formatangabe für das Datum ausgelesen... sowas kann bei neueren Versionen mit einem Volltextindex beschleunigt werden, aber besser wäre eine Konvertierung in eins der nativen Datumsformate.