Salut les agrumes !
Le constat
Je pars du constat (visible sur les stats Munin et GA) que nos pages de forum sont à la fois les plus visitées et les plus lourdes à charger.
En particulier, toutes ces pages font une quantité délirantes de requête, dont certaines pour des données qui sont systématiquement re-calculées à chaque affichage. En première approche, je pense à :
- Liste des forums : pour chaque catégorie, on recalcule :
- Nombre de sujets
- Nombre de messages
- Date du dernier message
- Titre du topic avec le dernier message
- Lien vers le dernier message
- Catégorie de forum : pour chaque sujet affiché, on recalcule :
- Nombre de réponses
- Date du dernier message
- Lien vers le dernier message
- Nom de l'auteur de ce message
- Lien vers l'auteur du dernier message
- (Les données du 1er message ne sont pas récupérées dans des requêtes dédiées)
- Page de forum : pour chaque message affiché, on recalcule :
- Le badge de l'auteur
La conséquence, c'est qu'on provoque systématiquement toutes les requêtes suivantes :
- Liste des forums : pour chaque catégorie :
- Compter les sujet
- Compter les messages
- Récupérer séparément l'objet
Post
du dernier message
- Catégorie de forum : pour chaque sujet affiché :
- Compter les réponses
- Récupérer séparément l'objet
Post
du dernier message - Récupérer séparément l'objet
Profile
du dernier posteur
- Page de forum : pour chaque message affiché :
- Une ou plusieurs requêtes spécifiques pour récupérer le badge (recalculé en fonction des droits du membre affiché)
Pour un membre connecté, on a d'autres problématiques qui viennent s'ajouter (en particulier la gestion des messages lus/non lus) mais là ça devient beaucoup plus compliqué à gérer, donc on ignore le problème pour l'instant.
Les requêtes en elle-même sont très rapides, mais leur multiplication fait qu'on passe un temps important en traitement Python sur ces requêtes (préparation, envoi au SGBD, récupération, etc).
Ça fait aussi que ces pages sont très sensibles aux lags de la BDD (on a aucune maîtrise sur les accès disques, et notre VPS fait un peur n'importe quoi de ce côté).
Comment régler le problème ?
Je vois 2 solutions sur lesquelles j'aimerais votre avis
Dé-normaliser le modèle
Il s'agit de mettre une copie des informations systématiquement recalculées dans la table "parente", comme c'est fait aujourd'hui avec les +1 / -1. Ces informations sont mises à jour au moment de l'enregistrement de l'enfant.
Exemple : les catégories contiendraient le nombre de topic, de messages et les informations sur le dernier message. Les forums contiendraient le nombre de message et les informations sur le dernier message et son auteur.
C'est assez simple à faire (sauf la migration de données pour dénormaliser le badge des membres). C'est simple à gérer parce que l'affichage se contente d'afficher une donnée de la base. Les pages ont un affichage optimisé par construction.
Par contre ça veut dire que les écritures sont beaucoup plus lourdes : par exemple, tout post de message irait mettre à jour la table des catégories, ce qui peut provoquer des problèmes.
Aussi, un bug dans une mise à jour risque de provoquer une désynchronisation des données dénormalisées, ce qui est chiant à corriger.
Mettre du cache sur ces informations spécifiquement
Là il s'agit de mettre en cache non pas les pages complètes (on ne peut pas vraiment, puisqu'elles sont très volatiles) mais uniquement les bouts d'informations qui nous intéressent.
C'est un peu plus compliqué à mettre en place, mais on s'affranchit complètement des problèmes d'engorgement en écriture et des désynchronisation.
L'utilisateur qui arrive sur une page avec un cache vide a une page un peu moins performante, mais comme notre site reste utilisable sans ce cache (signe d'un cache bien utilisé), ce n'est pas très gênant.
Le principal inconvénient c'est qu'on doit gérer un cache : ça implique d'éventuels problèmes de cache, et donc des bugs chiants s'ils arrivent dans ce système. Cela dit, là encore c'est sur des données non critiques donc au pire, c'est pas très grave.
Que pensez-vous de ces idées ?