La surcharge d'invalidation fréquente du cache de requêtes en vaut-elle la peine?

22

Je travaille actuellement sur une base de données MySQL où nous voyons un grand nombre d'invalidations du cache de requêtes, principalement en raison du nombre élevé d'instructions INSERT, DELETE et UPDATE qui sont exécutées sur de nombreuses tables.

Ce que j'essaie de déterminer, c'est s'il y a un quelconque avantage à autoriser le cache de requêtes à être utilisé pour les instructions SELECT qui sont exécutées sur ces tables. Puisqu'ils sont invalidés si rapidement, il me semble que la meilleure chose serait d'utiliser simplement SQL_NO_CACHE sur les instructions SELECT avec ces tables.

Le surcoût d'une invalidation fréquente en vaut-il la peine?

Edit: À la demande de l'utilisateur @RolandoMySQLDBA ci-dessous, voici les informations sur MyISAM et INNODB.

InnoDB

  • Taille des données: 177,414 Go
  • Taille de l'index: 114,792 Go
  • Taille de la table: 292,205 Go

MyISAM

  • Taille des données: 379,762 Go
  • Taille de l'index: 80.681 Go
  • Taille de la table: 460,443 Go

Information additionnelle:

  • Version: 5.0.85
  • query_cache_limit: 1048576
  • query_cache_min_res_unit: 4096
  • query_cache_size: 104857600
  • query_cache_type: ON
  • query_cache_wlock_invalidate: OFF
  • innodb_buffer_pool_size: 8841592832
  • 24 Go de RAM
Craig Sefton
la source
2
dom.as/tech/query-cache-tuner résume assez bien
Laurynas Biveinis
Hehe, très perspicace.
Craig Sefton

Réponses:

16

Vous devez simplement désactiver le cache de requête avec

[mysqld]
query_cache_size = 0

puis redémarrez mysql. Pourquoi est-ce que je suggérerais ça ???

Le cache de requêtes sera toujours en tête avec InnoDB. Ce serait bien si le MVCC d'InnoDB permettait aux requêtes d'être servies à partir du cache de requêtes si les modifications n'affectaient pas les lectures répétables pour d'autres transactions. Malheureusement, InnoDB ne fait tout simplement pas cela. Apparemment, vous avez beaucoup de requêtes qui sont invalidées assez rapidement et qui ne sont probablement pas réutilisées.

Pour InnoDB sous MySQL 4.0, le cache de requêtes a été désactivé pour les transactions. Pour MySQL 4.1+, InnoDB joue le flic du trafic lorsqu'il autorise l'accès au cache de requêtes par table.

Du point de vue de votre question, je dirais que la justification de la suppression du cache de requêtes n'est pas tant la surcharge, mais la façon dont InnoDB le gère.

Pour plus d'informations sur la façon dont InnoDB interagit avec le cache de requêtes, veuillez lire les pages 213 à 215 du livre "High Performance MySQL (Second Edition)" .

Si la totalité ou la majorité de vos données sont MyISAM, vous pouvez utiliser votre idée originale d'utiliser SQL_NO_CACHE.

Si vous avez un mélange d'InnoDB et de MyISAM, vous devrez trouver le bon équilibre pour votre application en fonction de la hauteur de vos échecs de cache. En fait, les pages 209-210 du même livre soulignent les raisons des échecs de cache:

  • La requête ne peut pas être mise en cache, soit parce qu'elle contient une construction non déterministe (telle que CURRENT_DATE), soit parce que son jeu de résultats est trop volumineux pour être stocké. Les deux types de requêtes non mises en cache incrémentent la variable d'état Qcache_not_cached.
  • Le serveur n'a jamais vu la requête auparavant, il n'a donc jamais eu la possibilité de mettre en cache son résultat.
  • Le résultat de la requête était précédemment mis en cache, mais le serveur l'a supprimé. Cela peut se produire parce qu'il n'y avait pas assez de mémoire pour le conserver, parce que quelqu'un a demandé au serveur de le supprimer ou parce qu'il a été invalidé

et les causes profondes des échecs de cache élevés avec peu de requêtes impossibles à mettre en cache peuvent être:

  • Le cache de requêtes n'est pas encore chaud. Autrement dit, le serveur n'a pas eu la possibilité de remplir le cache avec des jeux de résultats.
  • Le serveur voit des requêtes qu'il n'a jamais vues auparavant. Si vous n'avez pas beaucoup de requêtes répétées, cela peut se produire même après le réchauffement du cache.
  • Il existe de nombreuses invalidations de cache.

MISE À JOUR 2012-09-06 10:10 EDT

À la recherche de vos dernières informations mises à jour, vous avez query_cache_limitdéfini 1048576 (1M). Cela limite tout jeu de résultats à 1M. Si vous récupérez quelque chose de plus grand, il ne sera tout simplement pas mis en cache. Bien que vous ayez query_cache_sizedéfini 104857600 (100M), cela ne permet que 100 résultats mis en cache dans un monde parfait. Si vous effectuez des centaines de requêtes, la fragmentation se produira assez rapidement. Vous avez également 4096 (4K) comme jeu de résultats de taille minimale. Malheureusement, mysql n'a pas de mécanisme interne pour défragmenter le cache de requêtes.

Si vous devez avoir le cache de requêtes et que vous avez tellement de RAM, vous pouvez exécuter ce qui suit:

SET GLOBAL query_cache_size = 0;
SELECT SLEEP(60);
SET GLOBAL query_cache_size = 1024 * 1024 * 1024;

afin de purger le cache de requête. Vous perdez tous les résultats mis en cache, exécutez donc ces lignes pendant les heures creuses.

Je voudrais également attribuer les éléments suivants:

  • query_cache_size = 1G
  • query_cache_limit = 8M

Cela laisse 23G de RAM. Je voudrais soulever ce qui suit:

  • innodb_buffer_pool_size = 12G
  • key_buffer_size = 4G

Cela laisse 7G. Cela devrait être suffisant pour les connexions OS et DB.

Gardez à l'esprit que le tampon clé ne met en cache que les pages d'index MyISAM, tandis que le pool de tampons InnoDB met en cache les données et les index.

Une autre recommandation: passez à MySQL 5.5 pour pouvoir configurer InnoDB pour plusieurs CPU et plusieurs threads pour les E / S en lecture / écriture.

Voir mes articles précédents sur l'utilisation de MySQL 5.5 en conjonction avec l'accès à plusieurs processeurs pour InnoDB

MISE À JOUR 2012-09-06 14:56 EDT

Ma méthode pour effacer le cache de requête est plutôt extrême car elle arrose les données mises en cache et forme un segment de RAM complètement différent. Comme vous l'avez souligné dans votre commentaire, FLUSH QUERY CACHE(comme vous l'avez suggéré) ou même ce RESET QUERY CACHEserait mieux. Pour plus de précision, lorsque j'ai dit "pas de mécanisme interne", je voulais dire exactement cela. La défragmentation est nécessaire et doit être effectuée manuellement. Il devrait être contrôlé .

Si vous faites du DML (INSERT, UPDATEs, DELETEs) sur InnoDB plus souvent que sur MyISAM, je dirais supprimer complètement le cache de requête, ce que j'ai dit au début.

RolandoMySQLDBA
la source
Merci pour la réponse. J'ai ce livre et je l'utilise beaucoup; Je suis bien conscient des raisons pour lesquelles vous expliquez les échecs de cache, mais comme je l'ai mentionné, nous avons déjà identifié les invalidations de cache comme étant un problème clé en raison de la forte corrélation que nous constatons entre Com_select et Qcache_inserts. Oh, et la base de données en question a un mélange d'INNODB et de MyISAM.
Craig Sefton
Mis à jour avec les informations supplémentaires que vous avez demandées. Merci.
Craig Sefton
Merci pour la réponse, je me réjouis du reste. L'une des choses que nous avons identifiées était qu'environ 18% des requêtes n'étaient pas mises en cache, alors appréciez certainement les conseils concernant les paramètres. Malheureusement, la boîte n'est pas dédiée, mais vos recommandations devraient vous aider. La fragmentation est également un problème. Je suis toujours très préoccupé par le nombre d'invalidations que nous voyons (par opposition aux requêtes qui ne sont pas du tout mises en cache), donc je ne sais toujours pas si le surcoût en vaut la peine. J'apprécie vraiment votre perspicacité, merci beaucoup.
Craig Sefton
Concernant votre commentaire sur "mysql n'a pas de mécanisme interne pour défragmenter le cache de requête", ne pouvez-vous pas exécuter la commande FLUSH QUERY CACHEpour le défragmenter? Voir: dev.mysql.com/doc/refman/5.0/en/flush.html
Craig Sefton
Mis à jour ma réponse ...
RolandoMySQLDBA
3

MAUVAIS: query_cache_size = 1G

Pourquoi? En raison du temps que prendra une chasse d'eau. Autrement dit, lorsqu'une écriture se produit, l'intégralité de 1 Go sera analysé pour trouver toutes les références à la table qui a été modifiée. Plus le QC est grand, plus c'est lent. Je recommande une taille ne dépassant pas 50M, à moins que vos données ne changent rarement.

Le QC est à la fois pour MyISAM et InnoDB. Il supprime un Mutex mondial et le supprime trop tôt. Ce mutex est l'une des raisons pour lesquelles MySQL ne peut pas utiliser efficacement plus de 8 cœurs environ.

SQL_NO_CACHE n'est remarqué qu'après le verrouillage du Mutex! La seule utilisation de ce drapeau est le benchmarking.

Il est souvent préférable de donner la RAM à un autre cache.

Rick James
la source
2

Je peux penser à un cas parfait pour cela, et nous l'avons testé et exécuté en production ... Je l'appelle la stratégie de clustering "fast lane" :

Si vous effectuez un fractionnement en lecture-écriture avec un proxy comme MaxScale, ou si votre application est capable, vous pouvez envoyer certaines des lectures de ces tables rarement invalidées uniquement aux esclaves dont le cache de requêtes est activé, et le reste à d'autres esclaves avec lui éteindre.

Nous faisons cela et traitons 4M d'appels par minute au cluster lors de nos tests de charge (pas de référence ... la vraie affaire) en conséquence. L'application attend certaines choses sur master_pos_wait (), elle est donc limitée par le thread de réplication, et bien que nous l'avons vu avec un statut d'attente sur l'invalidation de Qcache à très haut débit, ces niveaux de débit sont plus élevés que le cluster n'est même capable de sans Qcache.

Cela fonctionne car il y a rarement quelque chose de pertinent dans le cache de requête minuscule sur ces machines à invalider (ces requêtes ne sont pertinentes que pour les tables rarement mises à jour). Ces boîtes sont notre "voie rapide". Pour le reste des requêtes que l'application fait, ils n'ont pas à faire face à Qcache car ils vont dans des boîtes sans qu'il ne soit activé.

Christopher McGowan
la source