Siehe Wie MySQL Indizes verwendet .
Überprüfen Sie auch, ob MySQL immer noch einen vollständigen Tabellenscanuser_metrics
hinzugefügt haben Tisch. In kleinen Tabellen ist der Zugriff nach Index tatsächlich teurer (I/O-weise) als ein Tabellen-Scan, und der Optimierer von MySQL könnte dies berücksichtigen.
Entgegen meinem vorherigen Post , stellt sich heraus, dass MySQL auch einen kostenbasierten Optimierer verwendet
, was sehr gute Neuigkeiten sind - vorausgesetzt, Sie führen Ihre ANALYZE
aus mindestens einmal, wenn Sie glauben, dass die Datenmenge in Ihrer Datenbank repräsentativ ist der zukünftigen täglichen Nutzung.
Beim Umgang mit kostenbasierten Optimierern (Oracle, Postgres usw.) müssen Sie sicherstellen, dass Sie regelmäßig ANALYZE
auf Ihren verschiedenen Tischen, wenn ihre Größe um mehr als 10-15% zunimmt. (Postgres erledigt dies standardmäßig automatisch für Sie, während andere RDBMS diese Verantwortung einem DBA, d. h. Ihnen, überlassen.) Durch statistische Analyse, ANALYZE
hilft dem Optimierer dabei, eine bessere Vorstellung davon zu bekommen, wie viel I/O (und andere zugehörige Ressourcen, wie z. B. CPU, die z. Fehler beim Ausführen von ANALYZE
kann zu sehr schlechten, manchmal katastrophalen Planungsentscheidungen führen (z. B. Millisekunden-Abfragen, die manchmal Stunden dauern, wegen schlecht verschachtelter Schleifen auf JOIN
s.)
Wenn die Leistung nach dem Ausführen von ANALYZE
immer noch unbefriedigend ist , dann können Sie das Problem normalerweise umgehen, indem Sie Hinweise verwenden, z. FORCE INDEX
, während Sie in anderen Fällen vielleicht über einen MySQL-Fehler gestolpert sind (z. B. diesen älteren , was Sie hätte gebissen können, wenn Sie nested_set
von Rails verwendet hätten ).
Nun, da Sie sich in einer Rails-App befinden , wird es umständlich (und macht den Zweck von ActiveRecord
zunichte ), um Ihre benutzerdefinierten Abfragen mit Hinweisen auszugeben, anstatt weiterhin den ActiveRecord
zu verwenden -generierte.
Ich hatte das in unserer Rails-Anwendung all erwähnt SELECT
Abfragen fielen nach dem Wechsel zu Postgres unter 100 ms, während einige der komplexen Joins von ActiveRecord
generiert wurden würde mit MySQL 5.1 aufgrund von verschachtelten Schleifen mit inneren Tabellenscans gelegentlich bis zu 15 Sekunden oder länger dauern, selbst wenn Indizes verfügbar waren. Kein Optimierer ist perfekt, und Sie sollten sich der Optionen bewusst sein. Andere potenzielle Leistungsprobleme, die Sie neben der Optimierung des Abfrageplans beachten sollten, sind Sperren. Dies liegt jedoch außerhalb des Bereichs Ihres Problems.