Nur frage mich , ob jemand von euch Menschen nutzen Count(1)
über , Count(*)
und wenn es einen spürbaren Unterschied in der Leistung ist oder wenn dies nur ein Vermächtnis Gewohnheit , die aus vergangenen Tagen Vergangenheit vorverlegt worden ist?
Die spezifische Datenbank ist SQL Server 2005
.
sql
sql-server
performance
super9
quelle
quelle
COUNT(*)
vsCOUNT(1)
vsCOUNT(pk)
- was ist besser? . Es gibt auchCOUNT(*)
vsCOUNT(column-name)
- was ist korrekter? . Es kann durchaus andere Duplikate geben.Antworten:
Es gibt keinen Unterschied.
Grund:
"1" ist ein Nicht-Null-Ausdruck. Es ist also dasselbe wie
COUNT(*)
. Der Optimierer erkennt es als das, was es ist: trivial.Das gleiche wie
EXISTS (SELECT * ...
oderEXISTS (SELECT 1 ...
Beispiel:
Gleiches IO, gleicher Plan, das funktioniert
Bearbeiten, August 2011
Ähnliche Frage auf DBA.SE .
Bearbeiten, Dezember 2011
COUNT(*)
wird speziell in ANSI-92 erwähnt (suchen Sie nach "Scalar expressions 125
")Das heißt, der ANSI-Standard erkennt, dass es offensichtlich blutet, was Sie meinen.
COUNT(1)
wurde aufgrund dieses Aberglaubens von RDBMS-Anbietern optimiert . Andernfalls würde es gemäß ANSI ausgewertetquelle
In SQL Server ergeben diese Anweisungen dieselben Pläne.
Entgegen der landläufigen Meinung tun sie dies auch in Oracle.
SYS_GUID()
in Oracle ist ziemlich rechenintensive Funktion.In meiner Testdatenbank
t_even
befindet sich eine Tabelle mit1,000,000
ZeilenDiese Abfrage:
wird für
48
Sekunden ausgeführt, da die Funktion jedenSYS_GUID()
zurückgegebenen Wert auswerten muss , um sicherzustellen, dass es sich nicht um einen handeltNULL
.Diese Abfrage:
läuft nur für
2
Sekunden, da es nicht einmal versucht zu bewertenSYS_GUID()
(obwohl*
es ein Argument dafür istCOUNT(*)
)quelle
SYS_GUID()
mindestens (ich meine genau) einmal ausgewertet werden , damit die Unterabfrage das Ergebnis zurückgibt, oder?COUNT(*)
von den Werten von abSYS_GUID
?COUNT(*)
die Ausführung, es braucht eine Tabelle, also sollte die Unterabfrage wie eine handeln. Ansonsten sehe ich keine MöglichkeitCOUNT(*)
, einen aussagekräftigen Wert zurückzugebenmap
Methode tut, sehen Sie, wie diese beiden Ausdrücke:t_even.map(() => sys_guid()).length
undt_even.length
würden immer den gleichen Wert zurückgeben? Der Optimierer von Oracle ist intelligent genug, um dasmap
Teil zu erkennen und zu optimieren .length
hängt nicht ganz davon ab, woraus die Sammlung besteht, sondern nur von der Anzahl ihrer Elemente. Wenn diese Nummer in den Metadaten der Sammlung gespeichert ist (dies ist nicht bei Oracle oder den meisten anderen modernen RDBMS der Fall, sondern bei der alten MySQL-Speicher-Engine MyISAM), mussCOUNT(*)
nur der Wert aus den Metadaten übernommen werden.Klar
COUNT(*)
undCOUNT(1)
wird immer das gleiche Ergebnis zurückgeben. Wenn einer langsamer als der andere wäre, wäre dies effektiv auf einen Optimierungsfehler zurückzuführen. Da beide Formulare in Abfragen sehr häufig verwendet werden, wäre es für ein DBMS nicht sinnvoll, einen solchen Fehler nicht behoben zu lassen. Daher werden Sie feststellen, dass die Leistung beider Formulare (wahrscheinlich) in allen wichtigen SQL-DBMS identisch ist.quelle
Ich arbeite im SQL Server-Team und kann hoffentlich einige Punkte in diesem Thread klären (ich hatte es zuvor noch nicht gesehen, es tut mir leid, dass das Engineering-Team dies zuvor noch nicht getan hat).
Erstens gibt es keinen semantischen Unterschied zwischen
select count(1) from table
vs.select count(*) from table
. Sie geben in allen Fällen die gleichen Ergebnisse zurück (und es ist ein Fehler, wenn nicht). Wie in den anderen Antworten angegeben,select count(column) from table
ist semantisch unterschiedlich und liefert nicht immer die gleichen Ergebnisse wiecount(*)
.Zweitens gibt es in Bezug auf die Leistung zwei Aspekte, die in SQL Server (und SQL Azure) von Bedeutung sind: Kompilierungszeitarbeit und Ausführungszeitarbeit. Die Kompilierungszeit ist eine trivial kleine Menge zusätzlicher Arbeit in der aktuellen Implementierung. In einigen Fällen wird das * auf alle Spalten erweitert, gefolgt von einer Reduzierung auf 1 Spalte, die ausgegeben wird, da einige der internen Operationen beim Binden und Optimieren funktionieren. Ich bezweifle, dass es in einem messbaren Test auftauchen würde, und es würde wahrscheinlich im Rauschen all der anderen Dinge verloren gehen, die unter der Decke passieren (wie automatische Statistiken, xevent-Sitzungen, Overhead des Abfragespeichers, Trigger usw.). Es sind vielleicht ein paar tausend zusätzliche CPU-Anweisungen. Damit, count (1) erledigt während der Kompilierung ein wenig weniger Arbeit (was normalerweise einmal vorkommt und der Plan über mehrere nachfolgende Ausführungen zwischengespeichert wird). Für die Ausführungszeit sollte es unter der Annahme, dass die Pläne gleich sind, keinen messbaren Unterschied geben. (Eines der früheren Beispiele zeigt einen Unterschied - es ist höchstwahrscheinlich auf andere Faktoren an der Maschine zurückzuführen, wenn der Plan identisch ist).
Wie der Plan möglicherweise anders sein kann. Dies ist äußerst unwahrscheinlich, aber in der Architektur des aktuellen Optimierers möglicherweise möglich. Das Optimierungsprogramm von SQL Server funktioniert als Suchprogramm (denken Sie: Computerprogramm, das Schach spielt und verschiedene Alternativen für verschiedene Teile der Abfrage durchsucht und die Alternativen berechnet, um den günstigsten Plan in angemessener Zeit zu finden). Diese Suche hat einige Einschränkungen hinsichtlich der Funktionsweise, um die Fertigstellung der Abfragekompilierung in angemessener Zeit zu gewährleisten. Für Abfragen, die über das Trivialste hinausgehen, gibt es Phasen der Suche, und sie behandeln Tranchen von Abfragen, basierend darauf, wie kostspielig der Optimierer die Ausführung der Abfrage für möglich hält. Es gibt drei Hauptsuchphasen, und in jeder Phase können aggressivere (teurere) Heuristiken ausgeführt werden, um einen günstigeren Plan als bei jeder früheren Lösung zu finden. Letztendlich gibt es am Ende jeder Phase einen Entscheidungsprozess, der versucht zu bestimmen, ob der bisher gefundene Plan zurückgegeben oder weiter gesucht werden soll. Bei diesem Prozess wird die bisher benötigte Gesamtzeit im Vergleich zu den geschätzten Kosten des besten bisher gefundenen Plans verwendet. Auf verschiedenen Computern mit unterschiedlichen CPU-Geschwindigkeiten ist es daher möglich (wenn auch selten), unterschiedliche Pläne zu erhalten, da in einer früheren Phase mit einem Plan eine Zeitüberschreitung auftritt und nicht in die nächste Suchphase übergegangen wird. Es gibt auch einige ähnliche Szenarien, die sich auf das Auslaufen der letzten Phase und möglicherweise auf den Speicher bei sehr, sehr teuren Abfragen beziehen, die den gesamten Speicher auf dem Computer belegen (normalerweise kein Problem bei 64-Bit, aber es war ein größeres Problem zurück auf 32-Bit-Servern). Wenn Sie einen anderen Plan erhalten, würde sich die Leistung zur Laufzeit letztendlich unterscheiden. Ich nicht
Net-Net: Bitte verwenden Sie eines der beiden gewünschten Elemente, da dies in keiner praktischen Form von Bedeutung ist. (Es gibt weitaus größere Faktoren, die die Leistung in SQL über dieses Thema hinaus ehrlich beeinflussen).
Ich hoffe das hilft. Ich habe ein Buchkapitel über die Funktionsweise des Optimierers geschrieben, aber ich weiß nicht, ob es angemessen ist, es hier zu veröffentlichen (da ich immer noch winzige Lizenzgebühren bekomme, glaube ich). Anstatt zu veröffentlichen, dass ich einen Link zu einem Vortrag bei SQLBits in Großbritannien veröffentlichen werde, in dem es darum geht, wie das Optimierungsprogramm auf hohem Niveau funktioniert, können Sie die verschiedenen Hauptphasen der Suche auf Wunsch etwas detaillierter sehen darüber zu lernen. Hier ist der Videolink: https://sqlbits.com/Sessions/Event6/inside_the_sql_server_query_optimizer
quelle
1
erfährt das auch die gleiche Erweiterung. Ich stütze mich dabei auf die Perf-Tests hier. Stackoverflow.com/questions/1597442/… siehe auch das Beispiel in dieser Antwort auf eine Abfrage, bei1
der unerwartet ein Fehler auftritt, wenn Berechtigungen auf Spaltenebene im Spiel sindBedeutet im SQL-92-Standard
COUNT(*)
speziell "die Kardinalität des Tabellenausdrucks" (kann eine Basistabelle, "VIEW", eine abgeleitete Tabelle, ein CTE usw. sein).Ich denke, die Idee war, dass
COUNT(*)
das leicht zu analysieren ist. Jede Äußerung unter Verwendung bedarf der Parser es keine Spalten verweisen , um sicherzustellen , (COUNT('a')
woa
eine wörtliche ist undCOUNT(a)
woa
eine Spalte kann zu unterschiedlichen Ergebnissen führen).Ebenso
COUNT(*)
kann es von einem mit den SQL-Standards vertrauten menschlichen Programmierer leicht ausgewählt werden. Dies ist eine nützliche Fähigkeit, wenn Sie mit dem SQL-Angebot mehrerer Anbieter arbeiten.Im speziellen Fall
SELECT COUNT(*) FROM MyPersistedTable;
wird davon ausgegangen, dass das DBMS wahrscheinlich Statistiken für die Kardinalität der Tabelle enthält.Deshalb benutze ich , weil
COUNT(1)
undCOUNT(*)
semantisch äquivalent sindCOUNT(*)
.quelle
COUNT(*)
undCOUNT(1)
sind im Falle von Ergebnis und Leistung gleich.quelle
Ich würde erwarten, dass der Optimierer sicherstellt, dass es außerhalb seltsamer Randfälle keinen wirklichen Unterschied gibt.
Wie bei allem ist die einzige Möglichkeit, dies zu erkennen, die Messung Ihrer spezifischen Fälle.
Das heißt, ich habe immer verwendet
COUNT(*)
.quelle
Da diese Frage immer wieder auftaucht, gibt es hier noch eine Antwort. Ich hoffe, dass ich hier etwas für Anfänger hinzufügen kann, die sich über "Best Practice" wundern.
SELECT COUNT(*) FROM something
zählt Datensätze, was eine einfache Aufgabe ist.SELECT COUNT(1) FROM something
Ruft eine 1 pro Datensatz ab und zählt dann die 1s, die nicht null sind, was im Wesentlichen Datensätze zählt, nur komplizierter.Trotzdem: Gute DBMS bemerken, dass die zweite Anweisung dieselbe Anzahl wie die erste Anweisung ergibt, und interpretieren sie entsprechend neu, um keine unnötige Arbeit zu leisten. In der Regel führen beide Anweisungen zum gleichen Ausführungsplan und benötigen dieselbe Zeit.
Aus Gründen der Lesbarkeit sollten Sie jedoch die erste Anweisung verwenden. Sie möchten Datensätze zählen, also Datensätze, keine Ausdrücke. Verwenden Sie COUNT (Ausdruck) nur, wenn Sie Vorkommen von etwas zählen möchten, die nicht null sind.
quelle
Ich habe einen Schnelltest unter SQL Server 2012 auf einer 8-GB-RAM-Hyper-V-Box durchgeführt. Sie können die Ergebnisse selbst sehen. Ich habe während der Ausführung dieser Tests keine andere Fensteranwendung außer SQL Server Management Studio ausgeführt.
Mein Tabellenschema:
Gesamtzahl der Datensätze in der
Employee
Tabelle: 178090131 (~ 178 Millionen Zeilen)Erste Abfrage:
Ergebnis der ersten Abfrage:
Zweite Abfrage:
Ergebnis der zweiten Abfrage:
Sie können feststellen, dass es einen Unterschied von 83 (= 70265 - 70182) Millisekunden gibt, der leicht auf den genauen Systemzustand zum Zeitpunkt der Ausführung von Abfragen zurückgeführt werden kann. Außerdem habe ich einen einzelnen Lauf durchgeführt, sodass dieser Unterschied genauer wird, wenn ich mehrere Läufe und eine Mittelung durchführe. Wenn für einen so großen Datensatz der Unterschied weniger als 100 Millisekunden beträgt, können wir leicht den Schluss ziehen, dass die beiden Abfragen keinen Leistungsunterschied aufweisen, den die SQL Server Engine aufweist.
Hinweis : RAM wird in beiden Läufen nahezu zu 100% ausgelastet. Ich habe den SQL Server-Dienst neu gestartet, bevor ich beide Läufe gestartet habe.
quelle
Ich habe dies hunderte Male ausgeführt und den Cache jedes Mal geleert. Die Ergebnisse variieren von Zeit zu Zeit, da die Serverlast variiert, haben aber fast immer
count(*)
eine höhere CPU-Zeit.quelle
count(*)
undcount(1)
Rück Ergebnisse innerhalb weniger ms voneinander, auch wenn eine Tabelle mit 4.500.000 Zeilen zu zählen, in meiner SQL 2008 - Instanz.Es gibt einen Artikel zeigt , dass die
COUNT(1)
auf Oracle ist nur ein AliasCOUNT(*)
, mit einem Nachweis darüber.Ich werde einige Teile zitieren:
Mit einem Benutzer mit
ALTER SESSION
Berechtigungen können Sie eine setzentracefile_identifier
, die Optimierungsverfolgung aktivieren und dieCOUNT(1)
Auswahl ausführen , wie :SELECT /* test-1 */ COUNT(1) FROM employees;
.Danach müssen Sie die Trace-Dateien lokalisieren, was getan werden kann
SELECT VALUE FROM V$DIAG_INFO WHERE NAME = 'Diag Trace';
. Später in der Datei finden Sie:Wie Sie sehen können, ist es nur ein Alias für
COUNT(*)
.Ein weiterer wichtiger Kommentar: Das
COUNT(*)
war vor zwei Jahrzehnten auf Oracle vor Oracle 7.3 wirklich schneller :Für andere Datenbanken als SQL Server sollte es für jede einzelne einzeln recherchiert werden.
Ich weiß, dass diese Frage spezifisch für SQL Server ist, aber die anderen Fragen zu SO zu demselben Thema, ohne die Datenbank zu erwähnen, wurden geschlossen und als aus dieser Antwort dupliziert markiert.
quelle
In allen RDBMS sind die beiden Zählmethoden hinsichtlich des Ergebnisses gleichwertig. In Bezug auf die Leistung habe ich keinen Leistungsunterschied in SQL Server festgestellt, aber es kann erwähnenswert sein, dass einige RDBMS, z. B. PostgreSQL 11, weniger optimale Implementierungen aufweisen,
COUNT(1)
da sie die Nullbarkeit des Argumentausdrucks überprüfen, wie in diesem Beitrag zu sehen ist .Ich habe beim Ausführen einen Leistungsunterschied von 10% für 1 Million Zeilen festgestellt:
quelle
COUNT (1) unterscheidet sich, wenn überhaupt, nicht wesentlich von COUNT (*). In Bezug auf die Zählung von NULL-fähigen Spalten kann dies unkompliziert sein, um die Unterschiede zwischen COUNT (*) und COUNT (<einige Spalten>) zu demonstrieren.
quelle