Warum ist eine Abfrage extrem langsam, obwohl die identische Abfrage in einer ähnlichen Tabelle im Handumdrehen ausgeführt wird

8

Ich habe diese Abfrage ... die extrem langsam läuft (fast eine Minute):

%Vor%

Die PRIME-Tabelle hat 18k Zeilen und PK auf PrimeId.

Die ATTRGROUP-Tabelle hat 24.000 Zeilen und hat eine zusammengesetzte PK auf PrimeId, col2, dann RelatedPrimeId und dann die Spalten 4-7. Es gibt auch einen separaten Index für RelatedPrimeId.

Die Abfrage gibt schließlich 8,5k Zeilen zurück - unterschiedliche Werte von PrimeId in der PRIME-Tabelle, die entweder PrimeId oder RelatedPrimeId in der Tabelle ATTRGROUP entsprechen

Ich habe die identische Abfrage mit ATTRADDRESS anstelle von ATTRGROUP. ATTRADDRESS hat eine identische Schlüssel- und Indexstruktur wie ATTRGROUP. Es hat nur 11k Zeilen darauf, die zwar kleiner ist, aber in diesem Fall läuft die Abfrage in etwa einer Sekunde und gibt 11k Zeilen zurück.

Also meine Frage ist das:

Wie kann die Abfrage trotz identischer Strukturen auf einer Tabelle so viel langsamer sein als auf der anderen?

Bisher habe ich dies in SQL 2005 versucht, und (unter Verwendung der gleichen Datenbank, aktualisiert) SQL 2008 R2. Zwei von uns haben unabhängig voneinander die gleichen Ergebnisse erhalten und dasselbe Backup auf zwei verschiedenen Computern wiederhergestellt.

Weitere Details:

  • das Bit innerhalb der Klammern läuft in weniger als einer Sekunde, auch in der langsamen Abfrage
  • Es gibt einen möglichen Hinweis im Ausführungsplan, den ich nicht verstehe. Hier ist ein Teil davon, mit einer verdächtigen 320.000.000 Zeilenoperation:

Allerdings ist die tatsächliche Anzahl der Zeilen in dieser Tabelle etwas über 24k, nicht 320M!

Wenn ich den Teil der Abfrage innerhalb der eckigen Klammern so umgestalte, dass er eine UNION anstatt eines OR verwendet, dann:

%Vor%

... dann dauert die langsame Abfrage weniger als eine Sekunde.

Ich würde mich sehr über jeden Einblick freuen! Lassen Sie mich wissen, wenn Sie weitere Informationen benötigen und ich werde die Frage aktualisieren. Danke!

Übrigens ist mir klar, dass es in diesem Beispiel einen redundanten Join gibt. Dies kann nicht einfach entfernt werden, da in der Produktion das Ganze dynamisch erzeugt wird und das Bit in den Klammern viele verschiedene Formen annimmt.

Bearbeiten :

Ich habe die Indizes auf ATTRGROUP neu erstellt, macht keinen signifikanten Unterschied.

Bearbeiten 2 :

Wenn ich eine temporäre Tabelle verwende, also:

%Vor%

... und dann wieder, sogar mit einem OR im ursprünglichen OUTER JOIN, läuft es in weniger als einer Sekunde. Ich hasse Temp-Tabellen wie diese, da es sich immer wie ein Eingeständnis der Niederlage anfühlt, also ist es nicht der Refactor, den ich benutzen werde, aber ich fand es interessant, dass es einen solchen Unterschied macht.

Bearbeiten 3 :

Das Aktualisieren der Statistiken macht auch keinen Unterschied.

Danke für all Ihre Vorschläge bis jetzt.

    
ChrisA 12.08.2011, 07:55
quelle

4 Antworten

6

Nach meiner Erfahrung ist es besser zwei linke Joins als ein OR in der JOIN-Klausel zu verwenden. Also statt:

%Vor%

Ich würde vorschlagen:

%Vor%     
WillMcKill 12.08.2011 08:51
quelle
3

Ich stelle fest, dass die Hauptabfrage nicht mit der Unterabfrage korreliert ist:

%Vor%

In dieser Konstruktion müssen Sie auch die Klausel 'is not null' nicht verwenden (werden Sie das jemals brauchen, da ein primarykey niemals einen Nullwert enthält?).

Mir wurde beigebracht, OR-Konstruktionen zu vermeiden (wie bereits von anderen empfohlen), aber auch, um eine "nicht null" oder "in Werteliste" zu vermeiden. Diese können meist durch eine (NOT) EXISTS-Klausel ersetzt werden.

    
Daan Remmers 25.11.2011 09:26
quelle
1

Dies ist keine direkte Antwort, aber wenn Sie FK-Constraints haben, die von ATTRGROUP.PrimeId und ATTRGROUP.RelatedPrimeId auf main verweisen, entspricht Ihre Abfrage diesem viel einfacheren:

%Vor%     
A-K 12.08.2011 14:54
quelle
0

Ein Grund, warum eine Abfrage in einer Tabelle viel langsamer sein kann als die andere, ist, dass die Statistiken in dieser Tabelle veraltet sind und der falsche Abfrageplan gewählt wird.

Ich unterstütze jedoch das Refactoring, das die oder die Klausel, die andere vorgeschlagen haben, loslässt.

    
HLGEM 12.08.2011 14:59
quelle

Tags und Links