Welche Art, eine Anzahl von Zeilen zu zählen, sollte in MySQL schneller sein?
Dies:
SELECT COUNT(*) FROM ... WHERE ...
Oder die Alternative:
SELECT 1 FROM ... WHERE ...
// and then count the results with a built-in function, e.g. in PHP mysql_num_rows()
Man würde denken, dass die erste Methode schneller sein sollte, da dies eindeutig ein Datenbankgebiet ist und das Datenbankmodul schneller als jeder andere sein sollte, wenn solche Dinge intern bestimmt werden.
mysql
performance
Franz
quelle
quelle
SELECT 1
und nichtSELECT *
. Ist da ein Unterschied?mysql_query()
, wird die gesamte Ergebnismenge von MySQL an PHP gesendet, unabhängig davon, was Sie tun mit diesen Daten machen.Antworten:
Wenn Sie
COUNT(*)
Zählspaltenindizes aufnehmen, ist dies das beste Ergebnis. MySQL mit MyISAM- Engine speichert tatsächlich die Zeilenanzahl. Es werden nicht alle Zeilen jedes Mal gezählt, wenn Sie versuchen, alle Zeilen zu zählen. (basierend auf der Spalte des Primärschlüssels)Die Verwendung von PHP zum Zählen von Zeilen ist nicht sehr klug, da Sie Daten von MySQL an PHP senden müssen. Warum tun Sie das, wenn Sie auf der MySQL-Seite dasselbe erreichen können?
Wenn das
COUNT(*)
langsam ist, sollten SieEXPLAIN
die Abfrage ausführen und prüfen, ob Indizes wirklich verwendet werden und wo sie hinzugefügt werden sollen.Das Folgende ist nicht der schnellste Weg, aber es gibt einen Fall, in dem
COUNT(*)
es nicht wirklich passt - wenn Sie mit dem Gruppieren von Ergebnissen beginnen, können Probleme auftreten, bei denenCOUNT
nicht wirklich alle Zeilen gezählt werden.Die Lösung ist
SQL_CALC_FOUND_ROWS
. Dies wird normalerweise verwendet, wenn Sie Zeilen auswählen, aber dennoch die Gesamtzahl der Zeilen kennen müssen (z. B. für das Paging). Wenn Sie Datenzeilen auswählen, fügen Sie einfach dasSQL_CALC_FOUND_ROWS
Schlüsselwort nach SELECT hinzu:Nachdem Sie die erforderlichen Zeilen ausgewählt haben, können Sie die Anzahl mit dieser einzelnen Abfrage ermitteln:
FOUND_ROWS()
muss sofort nach der Datenauswahlabfrage aufgerufen werden.Zusammenfassend hängt alles davon ab, wie viele Einträge Sie haben und was in der WHERE-Anweisung steht. Sie sollten wirklich darauf achten, wie Indizes verwendet werden, wenn viele Zeilen vorhanden sind (Zehntausende, Millionen und mehr).
quelle
MyISAM
Speichert die Zeilenanzahl. Andere Speicher-Engines wie speichernInnoDB
keine Zeilenzahlen und zählen jedes Mal alle Zeilen .SELECT 1 FROM ... LIMIT 1
oderSELECT COUNT(*) FROM ...
?WHERE
Klausel gibt.SELECT COUNT(*) FROM ...
kann viel Zeit in Anspruch nehmen, je nachdem, was gescannt werden muss (z. B. eine sehr große Tabelle oder ein Index von Millionen / Milliarden / Billionen Zeilen).SELECT 1 FROM ... LIMIT 1
kehrt sofort zurück, da Sie es auf die erste Zeile beschränken.Nachdem Ricardo mit meinen Teamkollegen gesprochen hatte, sagte er uns, dass der schnellere Weg ist:
Sie müssen sich jedoch daran erinnern, dass das Ergebnis möglicherweise nicht genau ist.
Sie können es auch über die Befehlszeile verwenden:
Weitere Informationen: http://dev.mysql.com/doc/refman/5.7/en/show-table-status.html
Eine vollständige Diskussion finden Sie auf mysqlperformanceblog
quelle
SHOW TABLE STATUS
(oder das ÄquivalentSELECT
ininformation_schema
) ist schnell, behandelt jedoch keineWHERE
Klausel. Es ist präzise für MyISAM, aber für InnoDB ungenau (manchmal um den Faktor 2).Tolle Frage, tolle Antworten. Hier ist eine schnelle Möglichkeit, die Ergebnisse wiederzugeben, wenn jemand diese Seite liest und diesen Teil vermisst:
quelle
as count
?id
ist auf den ersten Blick verwirrend.Diese Abfrage (ähnlich der von Bayuah geposteten ) zeigt eine schöne Zusammenfassung aller Tabellen in einer Datenbank: (vereinfachte Version der gespeicherten Prozedur von Ivan Cachicatari, die ich sehr empfehlen kann).
Beispiel:
quelle
information_schema
nicht mit dem Wert übereinstimmt, der vonSELECT count(*) FROM
InnoDB zurückgegeben wird, wenn InnoDB verwendet wird. Wenn Sie einen strengen Wert benötigen, beachten Sie, dass diese Methode nur bei MyISAM-Tabellen einen strengen Wert liefert. Mit InnoDB ist die Anzahl der Zeilen eine grobe Annäherung.Ich habe immer verstanden, dass das Folgende mir die schnellsten Antwortzeiten gibt.
quelle
SELECT 1 ...
gibt so viele Zeilen zurück wie dieWHERE
undLIMIT
fragen nach, und alle werden "1" sein.show table status like '<TABLE NAME>'
Dies wird viel schneller sein.WHERE
Klausel haben. Und für InnoDB ist es nur eine Schätzung.Wenn Sie die Anzahl der gesamten Ergebnismenge abrufen müssen, können Sie wie folgt vorgehen:
Dies ist normalerweise nicht schneller als die Verwendung,
COUNT
obwohl man denken könnte, dass das Gegenteil der Fall ist, da die Berechnung intern durchgeführt wird und die Daten nicht an den Benutzer zurückgesendet werden, sodass die Leistungsverbesserung vermutet wird.Das Ausführen dieser beiden Abfragen ist gut für die Paginierung, um Summen zu erhalten, aber nicht besonders für die Verwendung von
WHERE
Klauseln.quelle
Ich habe einige Benchmarks durchgeführt , um die Ausführungszeit von
COUNT(*)
vs zu vergleichenCOUNT(id)
(id ist der Primärschlüssel der Tabelle - indiziert).Anzahl der Versuche: 10 * 1000 Anfragen
Ergebnisse:
COUNT(*)
ist schneller 7%VIEW GRAPH: Benchmarkgraph
Mein Rat ist zu verwenden:
SELECT COUNT(*) FROM table
quelle
COUNT(1)
Versuche dies:
quelle
select count(*) from table_name
etwas anderes ausführen . dba.stackexchange.com/questions/151769/…Vielleicht möchten Sie eine
SELECT max(Id) - min(Id) + 1
. Dies funktioniert nur, wenn Ihre IDs sequentiell sind und Zeilen nicht gelöscht werden. Es ist jedoch sehr schnell.quelle
EXPLAIN SELECT id FROM ....
hat den Trick für mich gemacht. und ich konnte die Anzahl der Zeilen unter derrows
Spalte des Ergebnisses sehen.quelle
Ich habe Tische für die Bundesregierung mit manchmal 60 Millionen Datensätzen bearbeitet.
Und wir mussten die Gesamtzahl der Zeilen um ein Vielfaches kennen.
Deshalb haben wir Datenbankprogrammierer entschieden, dass in jeder Tabelle Datensatz eins immer der Datensatz ist, in dem die gesamten Datensatznummern gespeichert sind. Wir haben diese Nummer abhängig von den Zeilen INSERT oder DELETE aktualisiert.
Wir haben alle anderen Möglichkeiten ausprobiert. Dies ist bei weitem der schnellste Weg.
quelle
Eine count (*) -Anweisung mit einer where-Bedingung auf dem Primärschlüssel gab die Zeilenanzahl für mich viel schneller zurück, um einen vollständigen Tabellenscan zu vermeiden.
Das war für mich viel schneller als
quelle