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
?
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!
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.
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!
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!
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 ... :)
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
Es scheint, dass die Abfragen nicht genau gleich sind. Zumindest für MySQL.
Vergleichen Sie:
Die zweite Abfrage gibt zusätzlich "Using filesort" in Extra aus.
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.
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.
(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!)
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.)
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
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.
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.
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.