it-swarm.com.de

Was ist schneller, SELECT DISTINCT oder GROUP BY in MySQL?

Wenn ich einen Tisch habe

CREATE TABLE users (
  id int(10) unsigned NOT NULL auto_increment,
  name varchar(255) NOT NULL,
  profession varchar(255) NOT NULL,
  employer varchar(255) NOT NULL,
  PRIMARY KEY  (id)
)

und ich möchte alle eindeutigen Werte von profession erhalten, was schneller (oder empfohlen) wäre:

SELECT DISTINCT u.profession FROM users u

oder

SELECT u.profession FROM users u GROUP BY u.profession

?

260
vava

Sie sind im Wesentlichen einander äquivalent (tatsächlich implementieren einige Datenbanken DISTINCT unter der Haube).

Wenn einer von ihnen schneller ist, wird es DISTINCT sein. Dies liegt daran, dass ein Abfrageoptimierer, obwohl beide identisch sind, die Tatsache erfassen müsste, dass Ihr GROUP BY nutzt keine Gruppenmitglieder aus, nur deren Schlüssel. DISTINCT macht dies explizit, sodass Sie mit einem etwas dümmeren Optimierer davonkommen können.

Im Zweifelsfall testen!

238
SquareCog

Wenn Sie einen Index für profession haben, sind diese beiden Synonyme.

Wenn Sie dies nicht tun, verwenden Sie DISTINCT.

GROUP BY in MySQL sortiert die Ergebnisse. Sie können sogar tun:

SELECT u.profession FROM users u GROUP BY u.profession DESC

und sortiere deine Berufe in DESC Reihenfolge.

DISTINCT erstellt eine temporäre Tabelle und verwendet sie zum Speichern von Duplikaten. GROUP BY macht dasselbe, sortiert aber die eindeutigen Ergebnisse danach.

Damit

SELECT DISTINCT u.profession FROM users u

ist schneller, wenn Sie keinen Index für profession haben.

98
Quassnoi

Entscheiden Sie sich für das Einfachste und Kürzeste, wenn Sie können - DISTINCT scheint eher das zu sein, wonach Sie suchen, nur weil es Ihnen GENAU die Antwort gibt, die Sie brauchen, und nur das!

17
Tim

Alle obigen Antworten sind korrekt, für den Fall von DISTINCT in einer einzelnen Spalte und GROUP BY in einer einzelnen Spalte. Jede Datenbank-Engine hat ihre eigene Implementierung und Optimierung. Wenn Sie sich (in den meisten Fällen) für den sehr geringen Unterschied interessieren, müssen Sie einen Test mit einem bestimmten Server UND einer bestimmten Version durchführen! Da sich Implementierungen ändern können ...

ABER, wenn Sie mehr als eine Spalte in der Abfrage auswählen, ist das DISTINCT wesentlich anders! Denn in diesem Fall werden ALLE Spalten aller Zeilen anstatt nur einer Spalte verglichen.

Wenn Sie also etwas haben wie:

// This will NOT return unique by [id], but unique by (id,name)
SELECT DISTINCT id, name FROM some_query_with_joins

// This will select unique by [id].
SELECT id, name FROM some_query_with_joins GROUP BY id

Es ist ein häufiger Fehler zu glauben, dass das DISTINCT-Schlüsselwort Zeilen anhand der ersten von Ihnen angegebenen Spalte unterscheidet, das DISTINCT-Schlüsselwort jedoch auf diese Weise ein allgemeines Schlüsselwort ist.

Leute, ihr müsst also aufpassen, dass die obigen Antworten nicht für alle Fälle korrekt sind. Es kann zu Verwirrung und falschen Ergebnissen kommen, während alles, was ihr wollt, die Optimierung ist!

16
daniel.gindi

gut deutlich kann langsamer sein als Gruppe von in einigen Fällen in Postgres (weiß nicht über andere DBs).

getestetes Beispiel:

postgres=# select count(*) from (select distinct i from g) a;

count 

10001
(1 row)

Time: 1563,109 ms

postgres=# select count(*) from (select i from g group by i) a;

count
10001
(1 row)

Time: 594,481 ms

http://www.pgsql.cz/index.php/PostgreSQL_SQL_Tricks_I

also sei vorsichtig ... :)

7
OptilabWorker

Group by ist teurer als Distinct, da Group by das Ergebnis sortiert, während Distinct es vermeidet. Aber wenn Sie eine Gruppe bilden möchten, indem Sie dasselbe Ergebnis wie "distinct give order by null " liefern.

SELECT DISTINCT u.profession FROM users u

ist gleich

SELECT u.profession FROM users u GROUP BY u.profession order by null
7
Ranjith

Es scheint, dass die Abfragen nicht genau gleich sind. Zumindest für MySQL.

Vergleichen Sie:

  1. beschreibe einen bestimmten Produktnamen von northwind.products
  2. beschreiben Sie die Auswahl des Produktnamens aus der Gruppe northwind.products nach Produktname

Die zweite Abfrage gibt zusätzlich "Using filesort" in Extra aus.

5
amartynov

In MySQL "Group By "verwendet einen zusätzlichen Schritt: filesort. Mir ist klar, dass DISTINCT schneller ist als GROUP BY, und das war eine Überraschung.

3
Carlos

Hier ist ein einfacher Ansatz, der die 2 verschiedenen abgelaufenen Zeiten für jede Abfrage ausgibt.

DECLARE @t1 DATETIME;
DECLARE @t2 DATETIME;

SET @t1 = GETDATE();
SELECT DISTINCT u.profession FROM users u; --Query with DISTINCT
SET @t2 = GETDATE();
PRINT 'Elapsed time (ms): ' + CAST(DATEDIFF(millisecond, @t1, @t2) AS varchar);

SET @t1 = GETDATE();
SELECT u.profession FROM users u GROUP BY u.profession; --Query with GROUP BY
SET @t2 = GETDATE();
PRINT 'Elapsed time (ms): ' + CAST(DATEDIFF(millisecond, @t1, @t2) AS varchar);

ODER versuchen Sie SET STATISTICS TIME (Transact-SQL)

SET STATISTICS TIME ON;
SELECT DISTINCT u.profession FROM users u; --Query with DISTINCT
SELECT u.profession FROM users u GROUP BY u.profession; --Query with GROUP BY
SET STATISTICS TIME OFF;

Es wird lediglich die Anzahl der Millisekunden angezeigt, die zum Parsen, Kompilieren und Ausführen der einzelnen Anweisungen erforderlich sind:

 SQL Server Execution Times:
   CPU time = 0 ms,  elapsed time = 2 ms.
2
kolunar

(eher eine funktionale Anmerkung)

Es gibt Fälle, in denen Sie GROUP BY verwenden müssen, zum Beispiel, wenn Sie die Anzahl der Mitarbeiter pro Arbeitgeber ermitteln möchten:

SELECT u.employer, COUNT(u.id) AS "total employees" FROM users u GROUP BY u.employer

In einem solchen Szenario DISTINCT u.employer funktioniert nicht richtig. Vielleicht gibt es einen Weg, aber ich weiß es einfach nicht. (Wenn jemand weiß, wie man eine solche Abfrage mit DISTINCT macht, fügen Sie bitte eine Notiz hinzu!)

2
Ivan Dossev

Nach intensiven Tests kamen wir zu dem Schluss, dass GROUP BY schneller ist

SELECT sql_no_cache opnamegroep_intern FROM telwerken WHERE opnemergroep IN (7,8,9,10,11,12,13) ​​group by opnamegroep_intern

635 Gesamt 0,0944 Sekunden Weergave van records 0 - 29 (635 Gesamt, Abfrage duurde 0,0484 Sek.)

SELECT sql_no_cache distinct (opnamegroep_intern) FROM telwerken WHERE opnemergroep IN (7,8,9,10,11,12,13)

635 Gesamt 0,2117 Sekunden (fast 100% langsamer) Weergave van records 0 - 29 (635 Gesamt, Abfrage in 0,3468 Sek.)

1
Grumpy

Dies ist keine Regel

Versuchen Sie es für jede Abfrage separat und gruppieren Sie nach ... Vergleichen Sie die Zeit, um jede Abfrage abzuschließen, und verwenden Sie die schnellere.

In meinem Projekt verwende ich manchmal group by und andere distinct

1
user2832991

Wenn das Problem dies zulässt, versuchen Sie es mit EXISTS, da es so optimiert ist, dass es endet, sobald ein Ergebnis gefunden wird (und keine Antwort puffert). Wenn Sie also nur versuchen, Daten für zu normalisieren, eine WHERE-Klausel wie diese

SELECT FROM SOMETHING S WHERE S.ID IN ( SELECT DISTINCT DCR.SOMETHING_ID FROM DIFF_CARDINALITY_RELATIONSHIP DCR ) -- to keep same cardinality

Eine schnellere Antwort wäre:

SELECT FROM SOMETHING S WHERE EXISTS ( SELECT 1 FROM DIFF_CARDINALITY_RELATIONSHIP DCR WHERE DCR.SOMETHING_ID = S.ID )

Dies ist nicht immer möglich, aber wenn verfügbar, erhalten Sie eine schnellere Antwort.

0
Daniel R

SELECT DISTINCT ist immer gleich oder schneller als GROUP BY. Auf einigen Systemen (z. B. Oracle) kann es für die meisten Abfragen so optimiert werden, dass es mit DISTINCT identisch ist. Bei anderen (z. B. SQL Server) kann dies erheblich schneller sein.

0
Beep beep

Wenn Sie keine Gruppenfunktionen ausführen müssen (Summe, Durchschnitt usw., wenn Sie der Tabelle numerische Daten hinzufügen möchten), verwenden Sie SELECT DISTINCT. Ich vermute, es ist schneller, aber ich habe nichts zu zeigen.

Wenn Sie sich Gedanken über die Geschwindigkeit machen, erstellen Sie auf jeden Fall einen Index für die Spalte.

0
tehvan