Mysql
 sql >> Base de données >  >> RDS >> Mysql

MySQL n'utilise pas les index avec la clause WHERE IN ?

Voir Comment MySQL utilise les index .

Vérifiez également si MySQL effectue toujours une analyse complète de la table après avoir ajouté environ 2 000 lignes supplémentaires à vos user_metrics table. Dans les petites tables, l'accès par index est en fait plus coûteux (en termes d'E/S) qu'un balayage de table, et l'optimiseur de MySQL peut en tenir compte.

Contrairement à mon message précédent , il s'avère que MySQL utilise également un optimiseur basé sur les coûts , ce qui est une très bonne nouvelle, à condition que vous exécutiez votre ANALYZE au moins une fois lorsque vous estimez que le volume de données de votre base de données est représentatif de l'utilisation quotidienne future.

Lorsque vous traitez avec des optimiseurs basés sur les coûts (Oracle, Postgres, etc.), vous devez vous assurer d'exécuter périodiquement ANALYZE sur vos différentes tables car leur taille augmente de plus de 10-15%. (Postgres le fera automatiquement pour vous, par défaut, alors que d'autres RDBMS laisseront cette responsabilité à un DBA, c'est-à-dire vous.) Grâce à une analyse statistique, ANALYZE aidera l'optimiseur à avoir une meilleure idée de la quantité d'E/S (et d'autres ressources associées, telles que le processeur, nécessaires par exemple pour le tri) qui seront impliquées lors du choix entre différents plans d'exécution candidats. Échec de l'exécution de ANALYZE peut entraîner des décisions de planification très médiocres, parfois désastreuses (par exemple, des requêtes d'une milliseconde prenant parfois des heures en raison de mauvaises boucles imbriquées sur JOIN s.)

Si les performances ne sont toujours pas satisfaisantes après l'exécution de ANALYZE , vous pourrez alors généralement contourner le problème à l'aide d'astuces, par ex. FORCE INDEX , alors que dans d'autres cas, vous pourriez avoir trébuché sur un bogue MySQL (par exemple, cet l'ancien , qui aurait pu vous mordre si vous utilisiez le nested_set de Rails ).

Maintenant, puisque vous êtes dans une application Rails , ce sera lourd (et va à l'encontre de l'objectif de ActiveRecord ) pour émettre vos requêtes personnalisées avec des conseils au lieu de continuer à utiliser le ActiveRecord -générés.

J'avais mentionné que dans notre application Rails tous SELECT les requêtes ont chuté en dessous de 100 ms après le passage à Postgres, alors que certaines des jointures complexes générées par ActiveRecord prendrait parfois jusqu'à 15 secondes ou plus avec MySQL 5.1 en raison de boucles imbriquées avec des analyses de table internes, même lorsque des index étaient disponibles. Aucun optimiseur n'est parfait, et vous devez être conscient des options. D'autres problèmes de performances potentiels dont il faut être conscient, outre l'optimisation du plan de requête, sont le verrouillage. Cela sort cependant du cadre de votre problème.