Jeder weiß, dass in Tabellen, die InnoDB als Engine verwenden, Abfragen wie SELECT COUNT(*) FROM mytable
sehr ungenau und sehr langsam sind, insbesondere wenn die Tabelle größer wird und während der Ausführung dieser Abfrage ständig Zeilen eingefügt / gelöscht werden.
Wie ich es verstanden habe, speichert InnoDB die Zeilenzahl nicht in einer internen Variablen, was der Grund für dieses Problem ist.
Meine Frage ist: Warum ist das so? Wäre es so schwer, solche Informationen zu speichern? Es ist eine wichtige Information, in so vielen Situationen Bescheid zu wissen. Die einzige Schwierigkeit, die ich sehe, wenn eine solche interne Zählung implementiert würde, ist, wenn Transaktionen beteiligt sind: Wenn die Transaktion nicht festgeschrieben ist, zählen Sie die von ihr eingefügten Zeilen oder nicht?
PS: Ich bin kein Experte für DBs, ich bin nur jemand, der MySQL als einfaches Hobby hat. Also, wenn ich nur etwas Dummes gefragt habe, sei nicht übermäßig kritisch: D.
SELECT COUNT(*) FROM ...
Abfragen sind präzise. Wenn Sie möchten, kann phpMyAdmin so konfiguriert werden, dass auf Kosten der Geschwindigkeit immer exakte Zeilenzahlen verwendet werden. Weitere Informationen: stackoverflow.com/questions/11926259/…Antworten:
Ich stimme @RemusRusanu zu (+1 für seine Antwort)
SELECT COUNT(*) FROM mydb.mytable
in InnoDB verhält sich wie eine Transaktionsspeicher-Engine. Vergleichen Sie es mit MyISAM.MyISAM
Wenn
mydb.mytable
es sich um eine MyISAM-Tabelle handelt, ist das StartenSELECT COUNT(*) FROM mydb.mytable;
wie das AusführenSELECT table_rows FROM information_schema.table WHERE table_schema = 'mydb' AND table_name = 'mytable';
. Dies löst eine schnelle Suche nach der Zeilenzahl im Header der MyISAM-Tabelle aus.InnoDB
Wenn
mydb.mytable
es sich um einen InnoDB-Tisch handelt, ist einiges los. Sie haben MVCC und regeln Folgendes:Wenn Sie InnoDB nach einer Tabellenzahl fragen, müssen Sie durch diese bedrohlichen Dinge navigieren. Tatsächlich weiß man nie wirklich, ob
SELECT COUNT(*) from mydb.mytable
nur wiederholbare Lesevorgänge gezählt werden oder ob Lesevorgänge, die festgeschrieben wurden, und solche, die nicht festgeschrieben wurden, eingeschlossen sind.Sie könnten versuchen, die Dinge ein wenig zu stabilisieren, indem Sie innodb_stats_on_metadata aktivieren .
Gemäß der MySQL-Dokumentation zu innodb_stats_on_meta_data
Wenn Sie es deaktivieren, erhalten Sie möglicherweise eine stabilere Anzahl für das Einrichten von EXPLAIN-Plänen. Dies kann die Leistung
SELECT COUNT(*) from mydb.mytable
entweder positiv, negativ oder überhaupt nicht beeinflussen. Probieren Sie es aus und sehen Sie !!!quelle
Für den Anfang gibt es keinen "aktuellen Zähler", der in einer Variablen gespeichert werden kann. Eine Abfrage wie diese
SELECT COUNT(*) FROM ...
unterliegt der aktuellen Isolationsstufe und allen gleichzeitig ausstehenden Transaktionen. Abhängig von der Isolationsstufe kann die Abfrage Zeilen sehen oder nicht sehen, die durch ausstehende nicht festgeschriebene Transaktionen eingefügt oder gelöscht wurden. Die einzige Antwortmöglichkeit besteht darin, die Zeilen zu zählen, die für die aktuelle Transaktion sichtbar sind.Beachten Sie, dass ich das noch heiklere Thema gleichzeitiger Transaktionen, die während der Zählung beginnen oder enden, nicht einmal angerührt habe . Ganz zu schweigen von Rollbacks ...
quelle
COUNT(*)
Anfragen in der Realität selten benötigt und sind normalerweise das Ergebnis von Unerfahrenheit der Entwickler (Zählen der Zeilen, bevor wir sie auswählen!) Oder eines schlechten App-Designs.SELECT COUNT(*)
eine nicht optimierte hinzuWHERE
, und Sie haben einige Benutzer, die die Datenbank für einige fragwürdig nützliche Statistikzähler in die Knie zwingen.Während es theoretisch möglich wäre, mit InnoDB die Anzahl der Zeilen für eine bestimmte Tabelle genau zu zählen, würde dies viel Sperren kosten, was sich negativ auf die Leistung auswirken würde. Es würde sich auch aufgrund der Isolationsstufe unterscheiden.
MyISAM führt bereits das Sperren auf Tabellenebene durch, sodass keine zusätzlichen Kosten anfallen.
Ich benötige selten eine Zeilenanzahl für eine Tabelle, obwohl ich COUNT (*) ziemlich oft verwende. Ich habe im Allgemeinen eine WHERE-Klausel angehängt. Wenn ich einen effizienten Index für eine kleine Ergebnismenge verwende, finde ich, dass sie schnell genug sind.
Ich bin nicht einverstanden, dass die Zählungen ungenau sind. Die Zählungen stellen eine Momentaufnahme der Daten dar, und ich habe immer festgestellt, dass sie genau sind.
Kurz gesagt, MySQL überlässt es Ihnen, dies für InnoDB zu implementieren. Sie können eine Zählung speichern und nach jeder Abfrage erhöhen / verringern. Die einfachere Lösung ist wahrscheinlich der Wechsel zu MyISAM.
quelle