Oct/098
MySQL Query Cache
La query cache de MySQL joue un rôle important dans la performance de plusieurs sites Web. Elle a pour avantage d’être transparente, c’est-à-dire que la ou les applications qui s’en servent n’ont pas besoin d’être modifiées.
J’ai recu la semaine passée la question suivante (je résume):
Je souhaite utiliser une cache pour le menu de mon site afin de le rendre plus performant. Puisque le contenu du menu ne change pratiquement jamais, est-il plus avantageux d’utiliser APC Cache que la Query Cache de MySQL puisque la communication s’effectue selon un schéma comme:
php -> cache_apc (ram)
php -> mysql -> query_cache (ram)Je souhaite réduire au minimum les requêtes SQL exécutées.
Personnellement, j’utiliserais la cache de MySQL. Tout d’abord, il faut savoir qu’il y a une énorme différence entre les 2 caches.
MySQL Query Cache est centralisée sur le serveur MySQL, c’est-à-dire qu’elle utilise la RAM de la machine du serveur MySQL. Elle possède un mécanisme d’invalidation basique, mais efficace. L’invalidation se produit lorsque des valeurs d’une table sont en cache, et que ces valeurs sont mise à jour par une application ou manuellement par un utilisateur.
APC Cache est centralisée sur le serveur Web, c’est-à-dire qu’elle utilise la RAM disponible sur le serveur qui roule Apache et PHP (en supposant que vous utilisez Apache). Vous serez responsable d’invalider la cache lorsque nécessaire. Si quelqu’un modifie la valeur directement dans MySQL, la cache possèdera la vieille valeur jusqu’à ce qu’un processus l’invalide.
Puisque les données ne changent pratiquement jamais, je ne me casserais pas la tête à réinventer la roue. MySQL fait déjà pour vous ce que APC ferait, sans le moindre effort. De plus, il est plus ou moins vrai de dire que d’appeler la cache correspond à une requête. Oui, la string SQL est nécessairement envoyé à MySQL, mais lorsque celui-ci la reçoit et valide que cette requête est cachée, il retourne immédiatement le résultat sans rien “processer”. C’est comme ça que fonctionne APC aussi, il lui faut un identifiant unique pour associer le résultat, tout comme fait MySQL avec le HASH de la requête.
Les caches (peu importe laquelle) sont tout aussi efficaces avec une petite requête qui consomme peu de ressource qu’avec une grosse qui en demande beaucoup. Il est donc plus avantageux de cacher les processus lourds que les légers.
Ce qu’il faut surtout se soucier lorsqu’on utilise une cache, c’est comment et à quelle fréquence il faut l’invalider. Lorsque la Query Cache de MySQL est activée, le processus de cacher les résultats et de les invalider s’effectue tout seul de manière invisible. Ainsi, d’autres requêtes que vous ne soupçonnez même pas bénéficient de la cache. À l’inverse, il faut modifier le code pour chaque requête que vous souhaitez cacher avec APC.
Jun/080
Mesurer l’efficacité de la Query Cache
Il y a plusieurs moyens d’évaluer l’efficacité de la Query Cache. On peut se satisfaire de connaitre le nombre de hit à la cache versus le nombre de SELECT. La commande SHOW STATUS nous donne tout ce qu’on a besoin de savoir: Qcache_hits/(Com_select+Qcache_hits) ( notez que nous devons additionner Com_Select et Qcache_Hits car Com_Select n’est pas incrémenté lorsque le résultat est retourné par la cache).
Il y a certaines questions à se demander si vous obtenez un bas pourcentage. Quel genre de requêtes sont stockées en cache ? Est-ce que la cache crée une charge supplémentaire qui en vaut la peine ? On ne peut malheureusement pas savoir quelles requêtes sont dans la cache, mais on peut connaitre une partie de la surchage créé en calculant le taux d’invalidation des requêtes: (Com_insert+Com_delete+Com_update+Com_replace)/Qcache_hits
La variable Qcache_lowmem_prunes indique le nombre de requêtes qui ont été supprimées de la cache pour pouvoir en placer d’autres. Si le nombre est élevé, c’est un indice que la grosseur de la cache n’est pas suffisamment grande. Mais attention, si Qcache_free_memory indique qu’il y a de l’espace libre dans la cache, il n’est pas absolument nécessaire d’augmenter la taille de la cache.
Si le nombre d’insertions dans la cache est grand et que le nombre de hits est petit, c’est un autre indice que la cache n’est pas utilisée à son plein potentiel. Si le nombre de hits est réellement très bas, il serait peut-être mieux de ne pas utiliser la Query Cache du tout.
Il faut savoir faire un lien avec toutes les variables fournies par le serveur. Voici un exemple d’une serveur avec une relativement bonne utilisation de la Query Cache:
| Qcache_free_blocks | 29600 |
| Qcache_free_memory | 184098712 |
| Qcache_hits | 695816213 |
| Qcache_inserts | 254401651 |
| Qcache_lowmem_prunes | 1610387 |
| Qcache_not_cached | 31206222 |
| Qcache_queries_in_cache | 58357 |
| Qcache_total_blocks | 146413 |
| Com_select | 285585646 |
| Com_insert | 8810565 |
| Com_delete | 2633180 |
| Com_update | 593228 |
Qcache_hits/(Com_select+Qcache_hits) = 0.709
Plus la valeur est près de 1, mieux c’est.
(Com_insert+Com_delete+Com_update+Com_replace)/Qcache_hits = 0.4354
Plus la valeur est près de 0, mieux c’est.