PHPMyAdmin
Der fragende Sven
- datenbank
- mysql
Guten Abend,
wenn ich im PHPMyAdmin links auf eine Tabelle klicke, erhalte ich rechts davon die Anzahl wie viele Einträge vorhanden sind, richtig?
Wenn ich das erste mal die Seite aufrufe steht: Zeige Datensätze 0 - 24 (929 insgesamt, Die Abfrage dauerte 0.0003 Sekunden.) [ID: 1 - 1]
Wenn ich nochmals auf Anzeigen klicke steht Zeige Datensätze 0 - 24 (1118 insgesamt, Die Abfrage dauerte 0.0060 Sekunden.) [ID: 1 - 1]
Wenn ich nochmals klicke steht Zeige Datensätze 0 - 24 (1141 insgesamt, Die Abfrage dauerte 0.0012 Sekunden.) [ID: 1 - 1]
Wenn ich nochmals klicke steht Zeige Datensätze 0 - 24 (1095 insgesamt, Die Abfrage dauerte 0.0003 Sekunden.) [ID: 1 - 1]
Wenn ich nochmals klicke steht Zeige Datensätze 0 - 24 (1012 insgesamt, Die Abfrage dauerte 0.0002 Sekunden.) [ID: 1 - 1]
Wie kann es sein dass ich ständig unterschiedliche Werte erhalte? Und nein, es kann nicht sein dass im Hintergrund Daten eingetragen werden. Wie erhalte ich eine Zuverlässige Anzahl?
EDIT: Wenn ich mit COUNT() über PHP die Anzahl errechen lasse erhalte ich 929. Wie kann es also sein, dass ich im PHPMyAdmin ständig andere Daten angezeigt bekomme?
Zum Namen: Sven war leider schon vergeben
Tach!
wenn ich im PHPMyAdmin links auf eine Tabelle klicke, erhalte ich rechts davon die Anzahl wie viele Einträge vorhanden sind, richtig?
Jein - wie du ja selbst gesehen hast.
Wie kann es sein dass ich ständig unterschiedliche Werte erhalte?
Es gibt einen eigenen Zähler in den Tabellen. Bei der InnoDB-Engine sind da aber nur Schätzdaten zu bekommen.
Wie erhalte ich eine Zuverlässige Anzahl?
EDIT: Wenn ich mit COUNT() über PHP die Anzahl errechen lasse erhalte ich 929. Wie kann es also sein, dass ich im PHPMyAdmin ständig andere Daten angezeigt bekomme?
Selber zählen.
dedlfix.
Tach,
Selber zählen.
war wohl eher ein Witz? Kann ich mich wenigstens auf PHP verlassen?
Moin!
Tach,
Selber zählen.
war wohl eher ein Witz? Kann ich mich wenigstens auf PHP verlassen?
Es gibt in MySQL ein paar Wege, schnell an Informationen über den Zustand der Datenbank oder einzelner Tabellen zu kommen. Welche Wege das sind, und welche Qualität die Infos dann haben, hängt aber von der verwendeten Storage-Engine ab.
Bei MyISAM beispielsweise kriegst du immer die korrekte Anzahl der Datensätze. Bei InnoDB nur Schätzwerte. Für PHPMyAdmin, welches sowohl die verwendete Storage-Engine kennt, als auch diese schnellen Wege, ist es als Admin-Tool ausreichend, wenn bei InnoDB nur eine ungefähre Anzahl von Datensätzen angezeigt wird, denn es dürfte eher nicht als Bearbeitungstool für jeden einzelnen Datensatz genutzt werden. Die Anzeige der Anzahl der Datensätze soll nur vermitteln: Kleine Tabelle oder große Tabelle.
Wenn du die exakte Anzahl von Datensätzen wissen willst, bleibt dir nichts anderes übrig, als "SELECT COUNT(*) FROM table" auszuführen. Das ist immer korrekt, allerdings nicht immer performant - zumindest nicht so performant, wie man es bräuchte, wenn man ein allgemeines Browser-DB-Tool anbieten will.
Grüße Sven
Tach!
Selber zählen.
war wohl eher ein Witz? Kann ich mich wenigstens auf PHP verlassen?
Nein, kei Witz, ich meinte SELECT COUNT(*) FROM …, weil das die Datensätze zählt und nicht nur einen Wert aus der Metadatensammlung MySQLs abfragt. Das "selber" bezog sich darauf, dass du die Query selbst ausformulieren und absetzen musst, weil phpMyAdmin es nicht für dich tut. Und PHP hat damit nichts weiter zu tun, außer dass es das Ergebnis der Query abholt.
dedlfix.
Hallo Sven,
EDIT: Wenn ich mit COUNT() über PHP die Anzahl errechen lasse erhalte ich 929. Wie kann es also sein, dass ich im PHPMyAdmin ständig andere Daten angezeigt bekomme?
Dass das daran liegt, dass PHPMyAdmin die Statistik-Daten zu Rate zieht anstatt zu zählen haben dir ja schon die beiden anderen gesagt. Ich will noch kurz ausführen, warum PHPMyAdmin das macht.
InnoDB ist eine MVCC-Engine, wobei MVCC für Multiversion Concurrency Control steht. Das bedeutet, dass es pro Transaktion mehrere Status für den Datenbestand geben kann. Z.B. kann ein Datensatz, der durch ein INSERT
eingefügt wurde in einer Transaktion sichtbar sein (in der, in der das INSERT
abgefeuert wurde), in allen anderen aber nicht. Das gleiche gilt z.B. für Zeilen, die durch DELETE
oder UPDATE
verändert wurden.
Um also korrekt zu erkennen, wieviele Zeilen in dieser Transaktion vorhanden sind, kann MySQL keine Abkürzung nehmen (das ist bei MyISAM der Fall, hier kann er einfach in den Metadaten nachschauen wieviele Rows vorhanden sind) sondern muss jede einzelne Reihe überprüfen, also einen full table scan machen. Das ist nicht nur ordentlich Arbeit für die Datenbank sondern es führt auch dazu, dass der User lange warten muss. Übliche Varianten um das Problem zu umgehen sind endweder Zählertabellen (wenn man es wirklich genau wissen muss) oder halt das nachsehen in den Statistiken, die aber nur einen ungefähren Wert liefen.
Bei knapp 1000 Rows ist das noch nicht wirklich ein Problem, aber es soll dem Gerücht nach auch grössere Datenbanken geben... ;-)
LG,
CK
Hallo Christian,
Dass das daran liegt, dass PHPMyAdmin die Statistik-Daten zu Rate zieht anstatt zu zählen haben dir ja schon die beiden anderen gesagt. Ich will noch kurz ausführen, warum PHPMyAdmin das macht.
danke auch von meiner Seite für die ausführliche und einleuchtende Erklärung. Eine Sache bleibt aber trotzdem noch mysteriös, finde ich: Auch wenn die Anzahl der Datensätze aus Statistik-Daten "geschätzt" wird, sollte sich doch immer das gleiche Resultat ergeben, oder nicht? Denn der OP sagt ja, dass zwischen den Aufrufen von PMA keine Zugriffe auf die betroffene Tabelle stattfinden.
Lässt sich dieses Schwanken der Werte auch plausibel erklären?
So long,
Martin
Hallo Martin,
danke auch von meiner Seite für die ausführliche und einleuchtende Erklärung. Eine Sache bleibt aber trotzdem noch mysteriös, finde ich: Auch wenn die Anzahl der Datensätze aus Statistik-Daten "geschätzt" wird, sollte sich doch immer das gleiche Resultat ergeben, oder nicht?
Ich bin kein MySQL-Spezialist, bei PostgreSQL wäre das so, da werden die Statistiken in den System Catalogs gespeichert.
Aber soweit ich weiss arbeitet MySQL mit table samples, das heisst, dass es ein paar Pages von der Disk liest und anhand der Daten in den Pages und der Grösse der Relation auf der Platte auf die Tabelle schliesst. Die Page-Dichte allerdings variiert natürlich aufgrund von Faktoren wie Table Bloat und Füllmenge (nicht jede Page ist vollständig gefüllt).
Bzgl Table Bloat: der entsteht, wenn eine Zeile als gelöscht markiert werden muss. Das kann entweder passieren, wenn man sie via DELETE
wirklich löscht oder wenn man sie mit einem UPDATE
verändert. Es dürfte klar sein, warum bei einem DELETE
die Zeile nicht entfernt wird: einerseits wieder wegen MVCC, andererseits ist das auch eine Performance-Frage. Man müsste ja die darauf folgenden Rows nach oben „schieben“ auf der Platte und alle eventuellen Index-Verweise ändern. Also wird stattdessen die Row als gelöscht markiert. Bei einem UPDATE
gilt im wesentlichen das gleiche: die Reihe kann nicht einfach überschrieben werden, Stichwort MVCC. Also hängt man sie in einer neuen Version an die Tabelle an und markiert die alte Row als gelöscht.
Durch dieses Vorgehen entsteht sog. Table Bloat. Also im Grunde Löcher in den Tabellen-Files, die nicht benutzt werden können aber trotzdem gelesen werden müssen. Das ist der Grund, warum man regelmässig OPTIMIZE TABLE
ausführen will. Was „regelmässig“ in diesem Fall ist hängt natürlich von der Anwendung ab: bei wenigen Schreibzugriffen ist das seltener nötig.
So, ich hoffe ich habe nichts vergessen…
LG,
CK