896 Stimmen

Anzahl(*) vs. Anzahl(1) - SQL Server

Ich frage mich nur, ob jemand von Ihnen die Count(1) en Count(*) und ob es einen spürbaren Unterschied in der Leistung gibt oder ob dies nur eine alte Gewohnheit ist, die aus vergangenen Tagen mitgebracht wurde?

Die spezifische Datenbank ist SQL Server 2005 .

696voto

gbn Punkte 407102

Es gibt keinen Unterschied.

Der Grund:

Bücher online sagt " COUNT ( { [ [ ALL | DISTINCT ] expression ] | * } ) "

"1" ist ein Nicht-Null-Ausdruck: Es ist also dasselbe wie COUNT(*) . Der Optimierer erkennt sie als das, was sie ist: trivial.

Das Gleiche wie EXISTS (SELECT * ... o EXISTS (SELECT 1 ...

Beispiel:

SELECT COUNT(1) FROM dbo.tab800krows
SELECT COUNT(1),FKID FROM dbo.tab800krows GROUP BY FKID

SELECT COUNT(*) FROM dbo.tab800krows
SELECT COUNT(*),FKID FROM dbo.tab800krows GROUP BY FKID

Derselbe IO, derselbe Plan, das ganze Programm

Bearbeiten, August 2011

Ähnliche Frage auf DBA.SE .

Bearbeiten, Dezember 2011

COUNT(*) wird ausdrücklich erwähnt in ANSI-92 (suchen Sie nach " Scalar expressions 125 ")

Fall:

a) Wenn COUNT(*) angegeben ist, ist das Ergebnis die Kardinalität von T.

Das heißt, die ANSI-Norm erkennt an, dass es völlig offensichtlich ist, was Sie meinen. COUNT(1) wurde von RDBMS-Anbietern optimiert denn dieses Aberglaubens. Andernfalls würde es nach ANSI bewertet werden

b) Andernfalls sei TX die einspaltige Tabelle, die die Ergebnis der Anwendung des <Wertausdrucks> auf jede Zeile von T und der Eliminierung von Nullwerten. Wenn ein oder mehrere Nullwerte eliminiert werden eliminiert, wird eine Abschlussbedingung ausgelöst: Warnung-

108voto

Ich arbeite im SQL Server-Team und kann hoffentlich einige Punkte in diesem Thread klären (ich hatte ihn vorher nicht gesehen, daher tut es mir leid, dass das Ingenieurteam dies nicht schon früher getan hat).

Erstens gibt es keinen semantischen Unterschied zwischen select count(1) from table vs. select count(*) from table . Sie liefern in allen Fällen die gleichen Ergebnisse (und wenn nicht, handelt es sich um einen Fehler). Wie in den anderen Antworten erwähnt, select count(column) from table ist semantisch anders und liefert nicht immer die gleichen Ergebnisse wie count(*) .

Zweitens gibt es im Hinblick auf die Leistung zwei Aspekte, die bei SQL Server (und SQL Azure) von Bedeutung sind: Arbeit bei der Kompilierung und Arbeit bei der Ausführung. Der Aufwand für die Kompilierungszeit ist in der aktuellen Implementierung trivialerweise gering. In einigen Fällen kommt es zu einer Erweiterung der * auf alle Spalten, gefolgt von einer Reduzierung auf eine Spalte, die aufgrund der Art und Weise, wie einige der internen Operationen bei der Bindung und Optimierung funktionieren, ausgegeben wird. Ich bezweifle, dass sich dies in einem messbaren Test bemerkbar machen würde, und es würde wahrscheinlich im Rauschen all der anderen Dinge untergehen, die im Verborgenen passieren (wie z. B. Auto-Stats, Xevent-Sitzungen, Abfragespeicher-Overhead, Trigger usw.). Es sind vielleicht ein paar tausend zusätzliche CPU-Anweisungen. count(1) macht also ein winziges bisschen weniger Arbeit während der Kompilierung (die in der Regel einmal stattfindet und der Plan über mehrere nachfolgende Ausführungen hinweg zwischengespeichert wird). Was die Ausführungszeit angeht, sollte es keinen messbaren Unterschied geben, vorausgesetzt, die Pläne sind gleich. (Eines der früheren Beispiele zeigt einen Unterschied - dieser ist höchstwahrscheinlich auf andere Faktoren auf der Maschine zurückzuführen, wenn der Plan derselbe ist).

Wie kann der Plan möglicherweise anders aussehen? Es ist äußerst unwahrscheinlich, dass dies geschieht, aber bei der Architektur des aktuellen Optimierers ist es potenziell möglich. Der Optimierer von SQL Server funktioniert wie ein Suchprogramm (man denke an ein Schach spielendes Computerprogramm, das verschiedene Alternativen für verschiedene Teile der Abfrage durchsucht und die Alternativen durchrechnet, um den günstigsten Plan in angemessener Zeit zu finden). Diese Suche unterliegt einigen Einschränkungen, damit die Abfragekompilierung in angemessener Zeit abgeschlossen werden kann. Für Abfragen, die über die trivialsten hinausgehen, gibt es Suchphasen, die sich mit Tranchen von Abfragen befassen, je nachdem, wie kostspielig der Optimierer die potenzielle Ausführung der Abfrage einschätzt. Es gibt drei Hauptsuchphasen, und in jeder Phase können aggressivere (teure) Heuristiken ausgeführt werden, um einen Plan zu finden, der billiger ist als jede vorherige Lösung. Am Ende jeder Phase gibt es einen Entscheidungsprozess, der versucht zu bestimmen, ob der bisher gefundene Plan zurückgegeben oder die Suche fortgesetzt werden soll. Bei diesem Prozess wird die bisher benötigte Gesamtzeit gegen die geschätzten Kosten des besten bisher gefundenen Plans abgewogen. Auf verschiedenen Rechnern mit unterschiedlich schnellen CPUs ist es also möglich (wenn auch selten), unterschiedliche Pläne zu erhalten, weil man in einer früheren Phase mit einem Plan aufhört und in der nächsten Suchphase weitersucht. Es gibt auch einige ähnliche Szenarien im Zusammenhang mit der Zeitüberschreitung in der letzten Phase und dem potenziellen Auslaufen des Speichers bei sehr, sehr teuren Abfragen, die den gesamten Speicher des Rechners verbrauchen (normalerweise kein Problem auf 64-Bit-Servern, aber auf 32-Bit-Servern war dies ein größeres Problem). Letztendlich würde sich die Leistung zur Laufzeit unterscheiden, wenn Sie einen anderen Plan erhalten. Ich halte es für unwahrscheinlich, dass der Unterschied in der Kompilierungszeit JEMALS zu einer dieser Bedingungen führen würde.

Netz-Netz: Bitte verwenden Sie, was auch immer Sie wollen, da nichts davon in irgendeiner praktischen Form von Bedeutung ist. (Ehrlich gesagt gibt es weitaus größere Faktoren, die sich auf die Leistung von SQL auswirken als dieses Thema).

Ich hoffe, das hilft. Ich habe ein Buchkapitel darüber geschrieben, wie der Optimierer funktioniert, aber ich weiß nicht, ob es angemessen ist, es hier zu veröffentlichen (da ich, glaube ich, immer noch kleine Tantiemen dafür bekomme). Anstatt das zu posten, werde ich einen Link zu einem Vortrag posten, den ich auf der SQLBits in Großbritannien über die Funktionsweise des Optimierers auf hohem Niveau gehalten habe, damit Sie die verschiedenen Hauptphasen der Suche etwas detaillierter sehen können, wenn Sie mehr darüber erfahren möchten. Hier ist der Video-Link: https://sqlbits.com/Sessions/Event6/inside_the_sql_server_query_optimizer

81voto

Quassnoi Punkte 396418

In SQL Server ergeben diese Anweisungen die gleichen Pläne.

Entgegen der landläufigen Meinung tun sie das in Oracle auch.

SYS_GUID() in Oracle ist eine recht rechenintensive Funktion.

In meiner Testdatenbank, t_even ist eine Tabelle mit 1,000,000 Zeilen

Diese Abfrage:

SELECT  COUNT(SYS_GUID())
FROM    t_even

läuft für 48 Sekunden, da die Funktion jedes einzelne Element auswerten muss. SYS_GUID() zurück, um sicherzustellen, dass es sich nicht um eine NULL .

Aber diese Anfrage:

SELECT  COUNT(*)
FROM    (
        SELECT  SYS_GUID()
        FROM    t_even
        )

läuft für aber 2 Sekunden, da es nicht einmal versucht, die SYS_GUID() (trotz * Argument zu sein COUNT(*) )

77voto

Tony Andrews Punkte 125904

Das ist klar, COUNT(*) y COUNT(1) wird siempre liefern das gleiche Ergebnis. Wenn also einer langsamer wäre als der andere, wäre dies auf einen Fehler des Optimierers zurückzuführen. Da beide Formen sehr häufig in Abfragen verwendet werden, wäre es für ein DBMS nicht sinnvoll, einen solchen Fehler nicht zu beheben. Daher ist die Leistung beider Formen in allen großen SQL-DBMS (wahrscheinlich) identisch.

23voto

onedaywhen Punkte 52850

Im SQL-92-Standard, COUNT(*) bedeutet konkret "die Kardinalität des Tabellenausdrucks" (kann eine Basistabelle, `VIEW, abgeleitete Tabelle, CTE usw. sein).

Ich denke, die Idee war, dass COUNT(*) ist leicht zu parsen. Bei der Verwendung eines anderen Ausdrucks muss der Parser sicherstellen, dass dieser keine Spalten referenziert ( COUNT('a') donde a ist eine Worthülse und COUNT(a) donde a eine Spalte ist, kann zu unterschiedlichen Ergebnissen führen).

In der gleichen Weise, COUNT(*) können von einem Programmierer, der mit den SQL-Standards vertraut ist, leicht erkannt werden - eine nützliche Fähigkeit, wenn man mit mehreren SQL-Angeboten eines Anbieters arbeitet.

Auch im Sonderfall SELECT COUNT(*) FROM MyPersistedTable; Der Gedanke ist, dass das DBMS wahrscheinlich Statistiken über die Kardinalität der Tabelle führt.

Deshalb, weil COUNT(1) y COUNT(*) semantisch gleichwertig sind, verwende ich COUNT(*) .

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X