Après des années à ne pas comprendre pourquoi le count(*) était aussi long sur ma base à partir du moment où je la comptais à partir d’une View, j’ai drastiquement accéléré la requête. Quand je dis drastiquement je suis passé d’une dizaine de seconde à du quasi instantané et la consommation mémoire de la base a chu. L’analyse me montrait que le count(*) de la table principale de la view se faisait sur l’index alors que le count(*) sur la view déclenchait un full scan.
Dans un premier temps j’ai réécrit la view pour passer de jointures à gauche en étoile à des jointures en cascade, au passage un jointure à gauche est devenu une jointure normale. Cette modification améliorait un chouia le temps de réponse mais pas de manière transcendante.
Puis je suis tombé sur un article qui expliquant que l’opimiseur Innodb lors d’un count(*) n’utilisait pas le primary index, la répartition de celui-ci n’étant pas optimal, s’il y a un secondary index c’est celui-ci qui est utilisé sinon l’optimiseur cherche à déterminer quelle est la meilleur colonne pour le count(*).
Je n’y croyais pas mais effectivement le rajout d’un index « qui ne sert à rien mais sur une colonne petite » (dans mon cas le code postal) a suffit pour obtenir un temps de réponse canon pour le count(*) sur ma table de plus de 2 millions d’enregistrement.
Un grand Merci à Aaron Francis pour son éclairant article Is COUNT(*) slow in MySQL?