2012-06-07 7 views
8

Nun, vielleicht bin ich zu alt und ich möchte das folgende verstehen.Warum eine Union ist schneller als eine Gruppe von

Abfrage 1.

select count(*), gender from customer 
group by gender 

Abfrage 2.

select count(*), 'M' from customer 
where gender ='M' 
union 
select count(*), 'F' from customer 
where gender ='F' 

die erste Abfrage ist einfacher, aber aus irgendeinem Grund im Profiler, wenn ich beide zur gleichen Zeit ausführen, heißt es, dass Abfrage 2 verwendet 39% der Zeit und Abfrage 1 61%.

Ich möchte den Grund verstehen, vielleicht muss ich alle meine Fragen neu schreiben.

+1

Nur eine Vermutung: die zweite Abfrage hat eigentlich keine Aggregation, und kein Zustand wird beibehalten, um die Anzahl zu berechnen (es gibt nur die Anzahl der übereinstimmenden Zeilen für 'count (*)') – lanzz

+0

was meinst du 'at zur gleichen Zeit? – Sebas

+2

Ich nehme an, Sie haben nur 2 Geschlechter und jeder hat ein Geschlecht zugewiesen, anstatt dass einige "NULL" sind? Was ist, wenn Sie "UNION ALL" versuchen? Verbessert das die zweite noch mehr? Auch was RDBMS und wie sehen die Ausführungspläne aus? Auch die relativen Kosten in SQL Server-Ausführungsplänen spiegeln nicht unbedingt die tatsächliche Leistung wider, wenn Sie die beiden Abfragen vergleichen. –

Antwort

5

Ihre Abfrage 2 ist eigentlich ein netter Trick. Es funktioniert so: Sie haben einen Index über Geschlecht. Das DBMS kann diesen Index zweimal suchen, um zwei Zeilenbereiche zu erhalten (einen für M und einen für F). Es muss nichts aus diesen Zeilen lesen, nur dass sie existieren. Es kann die Anzahl der Zeilen in den zwei Bereichen zählen.

In der ersten Abfrage muss das DBMS die Zeilen dekodieren, um das Geschlecht zu lesen, dann muss es entweder die Zeilen sortieren oder eine Hashtabelle erstellen, um sie zu aggregieren. Das ist teurer als nur Zeilen zu zählen.

+0

Ein Index für Geschlecht könnte auch für ein Stream-Aggregat bei der ersten Abfrage verwendet werden. Keine Sortierung erforderlich, da sie bereits in der Indexreihenfolge sind. –

+0

Richtig, dennoch müssen die Zeilen decodiert und miteinander verglichen werden. – usr

+0

Die Zeilen müssen auch in einer Indexsuche dekodiert werden, damit sie weiß, wann sie die letzte Zeile erreicht hat, die dem Suchprädikat entspricht, und den Scanvorgang stoppen sollte. –

0

Die Optimierung einer Abfrage hängt von der Datenbank ab. Was Sie sehen, ist datenbankspezifisch.

Die Union, wie geschrieben, würde naiv zwei Durchläufe durch die Daten erfordern, einen Filter und eine Zählung durchführend. Grundsätzlich ist kein weiterer Speicher notwendig.

Die Aggregation könnte die Daten sortieren und dann zählen. Oder es könnte eine Hash-Tabelle generieren. Angesichts der Leistungsdifferenz würde ich vermuten, dass eine Sorte verwendet wird. Dies ist offensichtlich ein Overkill für diese Art von Abfrage.

Wenn Sie einen Index auf Geschlecht haben, würden beide Methoden scannen im Wesentlichen den Index so sollte die Leistung ähnlich sein (die Vereinigung Version könnte scannen sie zweimal =.

Ist die Datenbank, die Sie bieten eine Möglichkeit, verwenden zu Berechnen Sie Statistiken über Tabellen? Wenn ja, sollten Sie die Statistiken aktualisieren und sehen, ob Sie immer noch die gleichen Ergebnisse erhalten ..

Auch können Sie die Ergebnisse von "erklären" oder der Ausführungsplan? Das würde genau erklären, warum man ist schneller als der andere

2

Sind Sie sicher? Vielleicht der zweite q Es werden nur zwischenzeitlich zwischengespeicherte Ressourcen verwendet.

führen Sie sie in zwei separaten Batches und vor jedem Lauf DBCC FREEPROCCACHE, um den Cache zu reinigen. Vergleichen Sie dann die Werte jedes Ausführungsplans.

+1

Das wäre meine Vermutung – Filip

0

Ich habe eine äquivalente Abfrage versucht, aber das gegenteilige Ergebnis gefunden; die Gewerkschaft nahm 65% und die "Gruppe durch" 35%. (Verwenden von SQL Server 2008). Ich habe keinen Index für Geschlecht, daher zeigt mein Ausführungsplan einen Clustered-Index-Scan. Wenn Sie den Ausführungsplan nicht im Detail untersuchen, ist es wirklich nicht möglich, dieses Ergebnis zu erklären.

Das Hinzufügen eines Indexes für diese Abfrage ist wahrscheinlich keine gute Idee, da Sie diese Abfrage wahrscheinlich nicht so oft ausführen werden, wie Sie Datensätze in die Kundentabelle einfügen werden. In einigen anderen Datenbank-Engines mit Bitmap-Indizes (Oracle, PostgreSQL) kann das Datenbankmodul mehrere Indizes kombinieren, sodass sich der Nutzen von Indizes mit einer einzelnen Spalte ändern kann.In SQL Server müssen Sie die Indizes jedoch so entwerfen, dass sie die häufig verwendeten Abfragen abdecken.

Verwandte Themen