zestedesavoir / zds-site

Cœur du projet technique de Zeste de Savoir
https://zestedesavoir.com
Other
268 stars 162 forks source link

Limiter le nombre de requêtes SQL #407

Closed SpaceFox closed 10 years ago

SpaceFox commented 10 years ago

En réinstallant la debug_toolbar (qui marche très bien sous Windows, merci pour elle) pour regarder les bugs #393 et #406, je me suis aperçu que le site provoque un nombre complètement délirant de requêtes SQL :

Alors c'est relativement rapide, donc je suppose qu'il y a un cache quelque part. Mais ça n'en reste pas moins complètement hallucinant. Ça mériterait au moins de faire un test avec un vrai SGBD (genre pas Sqlite) pour savoir combien de ces requêtes arrivent jusqu'à lui.

firm1 commented 10 years ago

La pluspart des requêtes doivent être localisables dans le header (zone de notifs, zone d'alertes, zones de messages).

Les requetes sur les forums sont du principalement au fait qu'on essaye de savoir pour chaque membre qui poste, quel est son statut (banni, ls, staff, etc.). ça peut aussi être dénormalisé (mais avec plus de difficulté pour les LS/BAN temploraires)

SpaceFox commented 10 years ago

Quelques ressources : https://docs.djangoproject.com/en/1.6/topics/db/optimization/ https://docs.djangoproject.com/en/1.6/ref/models/querysets/#select-related

Le 2 mai 2014 19:12, firm1 notifications@github.com a écrit :

La pluspart des requêtes doivent être localisables dans le header (zone de notifs, zone d'alertes, zones de messages).

Les requetes sur les forums sont du principalement au fait qu'on essaye de savoir pour chaque membre qui poste, quel est son statut (banni, ls, staff, etc.). ça peut aussi être dénormalisé (mais avec plus de difficulté pour les LS/BAN temploraires)

— Reply to this email directly or view it on GitHubhttps://github.com/Taluu/ZesteDeSavoir/issues/407#issuecomment-42055109 .

Alex-D commented 10 years ago

Je pense, à vue de nez que les relations définies dans l'ORM sont en Lazy par défaut, et il faut les forcer pour qu'elles soient faites sous forme de jointures;

firm1 commented 10 years ago

Le Lazy est préférable dans la majeur partie des cas, sauf si on a vraiment envie de faire péter le serveur.

Alex-D commented 10 years ago

T'es conscient de l'impact de l'application du Lazy partout ? Si on laisse le lazy, il faut forcer les jointures là où c'est nécessaire.

firm1 commented 10 years ago

T'es conscient de l'impact de l'application du Lazy partout ?

C'est le contraire qui serait effrayant

Alex-D commented 10 years ago

Je n'ai pas dit de mettre de l'auto-jointure partout, seulement là où c'est fait systématiquement.

SpaceFox commented 10 years ago

AMHA, ça nécessiterait surtout l'aide de quelqu'un qui a de l'expérience dans ce genre de trucs.

Exemple : si j'ai bien compris ce que dit la doc et les requêtes que je vois passer, on ne récupère que les données des posts de la page (le bloc dans /ZesteDeSavoir/zds/forum/views.py ligne 105 ne correspond pas à une vraie requête). La requête réellement exécutée a une LIMIT qui correspond à la page courante.

Par contre j'ai l'impression qu'à cause des lignes 137 et 138 du même fichier on fait une requête par post présent dans la page pour en récupérer les données...

Bref, tout ça est assez compliqué et délicat.

Le 2 mai 2014 21:45, DEMODE Alexandre notifications@github.com a écrit :

Je n'ai pas dit de mettre de l'auto-jointure partout, seulement là où c'est fait systématiquement.

— Reply to this email directly or view it on GitHubhttps://github.com/Taluu/ZesteDeSavoir/issues/407#issuecomment-42070455 .

Alex-D commented 10 years ago

Je suis calé en SQL, mais pas en python/django.

Le res.append je pense que ça se contente juste de rebalancer le contenu du tableau posts dans la réponse.

Mais vu le nombre de requêtes il y a forcément un problème quelque part...

SpaceFox commented 10 years ago

Mais vu le nombre de requêtes il y a forcément un problème quelque part...

Le problème, c'est que je ne sais même pas quelle proportion de ces requêtes arrivent vraiment jusqu'au SGDB...

Le 2 mai 2014 22:16, DEMODE Alexandre notifications@github.com a écrit :

Je suis calé en SQL, mais pas en python/django.

Le res.append je pense que ça se contente juste de rebalancer le contenu du tableau posts dans la réponse.

Mais vu le nombre de requêtes il y a forcément un problème quelque part...

— Reply to this email directly or view it on GitHubhttps://github.com/Taluu/ZesteDeSavoir/issues/407#issuecomment-42074469 .

Coy0te commented 10 years ago

J'ai pas mal bossé sur ce genre de problématiques (affinage des requêtes SQL avec JPA, problématique identique à celle posée ici avec Django), je peux aider à défricher si besoin.

SpaceFox commented 10 years ago

Au vu des résultats des tests faits pour l'issue #413, en fait il n'y a pas de problème ici (soit il y a un cache, soit les requêtes sont tellement simples que non problématiques).

Il y a bien une question dans certains cas spécifiques, mais c'est le domaine des bugs #394 et #406 .

Du coup, je ferme celui-ci.

SpaceFox commented 10 years ago

Je ré-ouvre cette issue parce que les chiffres donnés par MySQL sont quand même flippant :

[--] Up for: 11d 16h 1m 1s (23M q [23.044 qps], 61K conn, TX: 28B, RX: 9B)

23 millions de requêtes en 11 jours, soit une moyenne (24h/24, 7j/7) de 24 requêtes par seconde. C'est juste dément par rapport au trafic qu'on a.

Alex-D commented 10 years ago

En fait, y a 1 chinois sur 5 qui a réussi à passer outre le htaccess :D

Plus sérieusement : les jointures les gars ! Les jointures...

Coy0te commented 10 years ago

@SpaceFox et les devs back : je ne sais pas comment fonctionne Django, donc je n'ose pas mettre les mains dedans, mais après survol de la doc ça m'a l'air de fonctionner derrière les rideaux à peu de choses près comme JPA.

Par défaut, tout est en mode requêtes "une par une", et c'est sûrement pour ça que c'est du gros n'importe quoi au niveau des perfs. L'argument évoqué précédemment du genre "c'est des requêtes simples donc c'est pas grave si y'en a une pelleté", c'est ok en dev voire en Beta mais c'est absolument pas scalable à des conditions de prod. J'espère d'ailleurs que Django gère une succession de requêtes d'un même utilisateur dans la même session, sinon bonjour l'explosion des ouvertures/fermetures de connexions... D'ailleurs (oui, encore un "d'ailleurs"), est-ce qu'on a un pool de connexions MySQL activé ? Comment est-il dimensionné ? Ça m'intéresse et je peux aider sur ce point si besoin.

Pour en revenir aux requêtes, il faut examiner chacune des requêtes impliquant potentiellement des jointures, et décider de les activer (ou non, dans de rares cas).

SpaceFox commented 10 years ago

Je n'ai pas la moindre info là-dessus... Il nous faudrait l'avis et un peu de temps d'un connaisseur de Django.

Pour le pool de connexion, personnellement je n'ai rien configuré... j'ose espérer qu'il y en a un dans un coin !

geoffreyc commented 10 years ago

Je sais que dans pas mal d'app django, ya beaucoup d'erreurs du genre des "select" dans les loops, etc. (a cause du ORM django qui rend ca super simple a faire ...) ducoup je sais pas si c'est le cas ici, mais il faudrait deja faire un tour peut partout pour voir si ya pas des endroits ou on a oublié de faire des "prefetch_related par example. Avec un nombre pareil de queries, ca m’entonnerait pas qu'on ait cette situation de "select in a loop"

2014-06-16 20:54 GMT+01:00 Coyote notifications@github.com:

requêtes impliquant potentiellement des jointures, et décider de les activer (ou non, dans de rares cas).

firm1 commented 10 years ago

Ah cette issue aussi peut être fermée, Maintenant que les templates sont stables, j'ai passé un gros coup de balai dans les requêtes. Le nombre de requêtes a été réduit d'au moins 1/3 dans le pire des cas.

Voici un résumé des nouvelles perfs :

Pour comparaison : Prod vs Preprod (qui est actuellement sur la PR 1030).

NB : la préprod est ISO-PROD en terme de matériels et de logiciel. et la préprod a plus de topics dans le forum que la prod.

Pages url Temps de chargement prod Temps de chargement préprod Ratio
Home / 1.012 seconds 0.074 seconds 13.67
Liste des catégories /forums/communaute/ 1.234 seconds 0.370 seconds 3.33
Liste des forums /forums/communaute/bug-suggestions/ 1.307 seconds 0.622 seconds 2.1
Un topic /forums/sujet/273/les-petits-pixels/ 2.927 seconds 0.710 seconds 4.12

Donc la PR permet d'afficher les pages entre 2 et 13 fois plus vite avec la PR.