Mysql
 sql >> Datenbank >  >> RDS >> Mysql

MySQL EXPLAIN 'type' ändert sich von 'range' zu 'ref', wenn das Datum in der where-Anweisung geändert wird?

Für unterschiedliche Daten sind unterschiedliche Suchstrategien sinnvoll. Insbesondere Index-Scans (z. B. Range) müssen häufig suchen, um die Zeile tatsächlich zu lesen. Irgendwann ist es langsamer, all diese Suchvorgänge durchzuführen, als den Index überhaupt nicht zu verwenden.

Nehmen wir ein triviales Beispiel, eine Tabelle mit drei Spalten:ID (Primärschlüssel), Name (indiziert), Geburtstag. Angenommen, es hat viele Daten. Wenn Sie MySQL bitten, nach Bobs Geburtstag zu suchen, kann es das ziemlich schnell tun:Zuerst findet es Bob im Namensindex (das dauert ein paar Suchen, log(n), wobei n die Zeilenanzahl ist), dann eine weitere Suche Lesen Sie die aktuelle Zeile in der Datendatei und lesen Sie den Geburtstag daraus. Das geht sehr schnell und viel schneller, als die gesamte Tabelle zu scannen.

Als nächstes ziehen Sie in Erwägung, einen name like 'Z%' zu verwenden . Das ist wahrscheinlich ein ziemlich kleiner Teil des Tisches. Es ist also noch schneller zu finden, wo die Zs im Namensindex beginnen, und dann für jedes die Datendatei zu suchen, um die Zeile zu lesen. (Dies ist ein Bereichsscan).

Erwägen Sie schließlich, nach allen Namen zu fragen, die mit M-Z beginnen. Das ist wahrscheinlich etwa die Hälfte der Daten. Es könnte einen Bereichsscan machen und dann viel von Suchvorgängen, aber das zufällige Durchsuchen der Datendatei mit dem ultimativen Ziel, die Hälfte der Zeilen zu lesen, ist nicht optimal:Es wäre schneller, nur einen großen sequentiellen Lesevorgang über die Datendatei durchzuführen. In diesem Fall wird der Index also ignoriert.

Dies ist, was Sie sehen – außer in Ihrem Fall gibt es einen anderen Schlüssel, auf den es zurückgreifen kann. (Es ist auch möglich, dass es tatsächlich den Datumsindex verwendet, wenn es den anderen nicht hat, es sollte den Index auswählen, der am schnellsten ist. Beachten Sie, dass der Optimierer von MySQL dabei häufig Fehler macht.)

Kurz gesagt, dies wird erwartet. Eine Abfrage sagt nicht wie um die Daten abzurufen, sondern es sagt was Daten abzurufen. Der Optimierer der Datenbank soll den schnellsten Weg finden, sie abzurufen.

Möglicherweise finden Sie einen Index zu beidem Spalten in der Reihenfolge (public_key,created_on_date) wird in beiden Fällen bevorzugt und beschleunigt Ihre Abfrage. Dies liegt daran, dass MySQL immer nur einen Index pro Tabelle (pro Abfrage) verwenden kann. Außerdem steht das Datum am Ende, da ein Bereichsscan nur für die letzte Spalte in einem Index effizient durchgeführt werden kann.

[InnoDB hat tatsächlich eine weitere Ebene der Indirektion, glaube ich, aber es würde den Punkt nur verwirren. Es ändert nichts an der Erklärung.]