Warum ist count (*) langsam, wenn explain die Antwort kennt?

13

Diese Abfrage select count(*) from planner_eventdauert sehr lange. Ich habe sie aufgegeben und getötet, bevor sie beendet war. Beim Ausführen explain select count(*) from planner_eventsehe ich jedoch eine Spalte in der Ausgabe mit der Anzahl der Zeilen (14 m).

Wie kommt es, dass EXPLAIN die Anzahl der Zeilen sofort ermitteln kann, die Ausführung von count (*) jedoch lange dauert?

Benubird
quelle
COUNT (*) ohne WHERE-Ursache führt zu einer Tabellensuche in der InnoDB-Engine. MyISAM kann die Zählung direkt übermitteln, da COUNT in der Header-Datei nicht in der Tabelle enthalten ist.
Raymond Nijland

Antworten:

15

Erklären Sie, dass zuvor erfasste Statistiken verwendet werden (die vom Abfrageoptimierer verwendet werden). Durch einen select count(*)Lesevorgang wird JEDER Datenblock gelesen.

Hier ist ein günstiger Weg, um eine geschätzte Zeilenanzahl zu erhalten:

select TABLE_ROWS FROM INFORMATION_SCHEMA.TABLES where TABLE_NAME='planner_event';

Selbst wenn Sie dies getan haben select count(id), kann es noch sehr lange dauern, es sei denn, Sie haben einen Sekundärindex aktiviert id(vorausgesetzt, es idhandelt sich um einen Primärschlüssel). Da alle Daten (einschließlich Zeilendaten) in B-Tree-Indizes gespeichert sind, ist die Ausführung von a select count(PK_COLUMN)immer noch eine erhebliche Menge an E / A-Vorgängen (zum Lesen aller Datenseiten erforderlich). Wenn Sie einen sekundären Index für das PK-Feld haben, kann es weniger E / A-Vorgänge ausführen, um eine Zählung durchzuführen.

Kevin Bott
quelle
I_S.TABLES gibt Ihnen die gleiche Schätzung , EXPLAINdie Sie erhalten.
Rick James
Die Abfrage fehlt AND TABLE_SCHEMA='my_database', andernfalls erhalten Sie mehrere Ergebnisse zurück, wenn Sie eine Tabelle mit demselben Namen in einer anderen Datenbank haben.
cz
3

Erläutern Sie, dass die Zahl aus einigen "Statistiken" stammt, die zum Schätzen von Dingen für den Optimierer verwendet werden. Diese Zahl kann alles andere als korrekt sein - ich sehe manchmal, dass sie um mehr als den Faktor 2 (höher oder niedriger) über dem exakten Wert liegt.

Bei der COUNT(*)Ausführung von in einer InnoDB-Tabelle muss die Tabelle gescannt werden, um zu vermeiden, dass Datensätze falsch gezählt werden, die gerade von anderen Verbindungen eingefügt / gelöscht, aber noch nicht "festgeschrieben" wurden. Eigentlich ist es gut genug, einen vollständigen Scan für einen Index durchzuführen, nicht unbedingt für die gesamte Tabelle (die den enthält PRIMARY KEY).

Wie viel RAM hast du? Was ist der Wert von innodb_buffer_pool_size? Es könnte helfen, wenn das ungefähr 70% des RAM wären.

Rick James
quelle