Dies liegt an der, wie ich es nenne, 5 %-Regel basierend auf der Schlüsselpopulation (Tupelkardinalität).
Wenn Sie eine Tabelle mit einseitiger Kardinalität indizieren, wählt der MySQL-Abfrageoptimierer immer den Weg des geringsten Widerstands.
BEISPIEL :Wenn eine Tabelle eine Geschlechterspalte hat, ist die Kardinalität zwei, M und F.
Was ist ein Index für eine solche Geschlechterspalte ??? Sie erhalten im Wesentlichen zwei riesige verknüpfte Listen.
Wenn Sie eine Million Zeilen in eine Tabelle mit einer Geschlechtsspalte laden, erhalten Sie möglicherweise 50 % M und 50 % F.
Ein Index wird während der Abfrageoptimierung nutzlos, wenn die Kardinalität einer Schlüsselkombination (Schlüsselpopulation, wie ich es ausdrücke) mehr als 5 % der gesamten Tabellenanzahl beträgt.
Nun, in Bezug auf Ihr Beispiel, warum die beiden unterschiedlichen EXPLAIN-Pläne ??? Meine Vermutung ist der MySQL Query Optimizer und InnoDB als Tag-Team.
Beim ersten CREATE TABLE sind die Tabelle und die Indizes ungefähr gleich groß, aber klein, also es entschied sich für den Index, indem es einen Index-Scan und keinen vollständigen Tabellen-Scan durchführte . Denken Sie daran, dass nicht eindeutige Indizes den internen Primärschlüssel (RowID) jeder Zeile in ihren Indexeinträgen enthalten, wodurch die Indizes fast dieselbe Größe wie die Tabelle selbst haben.
Im zweiten CREATE TABLE bringen Sie durch die Einführung einer weiteren Spalte, user, den Query Optimizer jetzt dazu, ein völlig anderes Szenario zu sehen:Die Tabelle ist jetzt größer als die Indizes . Daher wurde der Abfrageoptimierer bei seiner Interpretation der Verwendung verfügbarer Indizes strenger. Es ging um die 5%-Regel, die ich zuvor erwähnt habe. Diese Regel schlug kläglich fehl und der Abfrageoptimierer entschied sich für einen vollständigen Tabellenscan.