Development #54747
Déléguer le calcul de Event.full à la base de donnée
0%
Description
Par exemple en utilisant un trigger, ça concerne également Event.almost_full.
(utile notamment pour simplifier la réservation en masse introduite par #54332, où des annotations compliquées sont nécessaires pour maintenir ces flags)
Fichiers
Demandes liées
Révisions associées
Historique
Mis à jour par Valentin Deniaud il y a presque 3 ans
- soit on traduit vraiment ce qu'on fait actuellement en django en SQL, genre à chaque fois qu'un booking est créé, compter le nombre de bookings de l'évènements et en déduire full (et donc la création d'un booking entraîne toujours une requête count)
- soit on crée un nouveau champ booking_count sur un évènement, on fait +1/-1 si un booking est créé/annulé et on met full à jour à partir de booking_count
J'ai envie de partir sur l'option 2 mais comme j'y connais rien je pose ça ici.
Mis à jour par Lauréline Guérin il y a presque 3 ans
ça se gère très bien à coup de trigger + champ readonly côté django pour éviter les surcharges par erreur; je peux proposer un truc à l'occasion
(j'ai déjà écrit des trucs comme ça par le passé)
Mis à jour par Lauréline Guérin il y a plus de 2 ans
- Echéance mis à 16 août 2021
- Début changé de 10 juin 2021 à 16 août 2021
- Suit Development #56148: Supprimer les références à sqlite ajouté
Mis à jour par Lauréline Guérin il y a plus de 2 ans
- Echéance
16 août 2021supprimé - Début
16 août 2021supprimé
Mis à jour par Lauréline Guérin il y a plus de 2 ans
- Fichier 0001-agendas-trigger-full-and-places-event-fields-54747.patch 0001-agendas-trigger-full-and-places-event-fields-54747.patch ajouté
- Statut changé de Nouveau à Solution proposée
- Patch proposed changé de Non à Oui
Pour simplifier les triggers, et aussi parce qu'on utilise souvent cette information (qu'on va chercher à coup d'annotations), j'ai ajouté des compteurs booked_places
et booked_waiting_list_places
On pourrait simplifier encore un peu les triggers, et surtout les déclencher moins souvent, en ajoutant une app comme django-readonly-field (https://pypi.org/project/django-readonly-field/), qui garantirait que les compteurs et les bool full/almost_full ne sont pas modifiés par le code.
Mais ça fait une contrib de plus à intégrer.
Mis à jour par Benjamin Dauvergne il y a plus de 2 ans
- Statut changé de Solution proposée à Solution validée
Lauréline Guerin a écrit :
Pour simplifier les triggers, et aussi parce qu'on utilise souvent cette information (qu'on va chercher à coup d'annotations), j'ai ajouté des compteurs
booked_places
etbooked_waiting_list_places
On pourrait simplifier encore un peu les triggers, et surtout les déclencher moins souvent, en ajoutant une app comme django-readonly-field (https://pypi.org/project/django-readonly-field/), qui garantirait que les compteurs et les bool full/almost_full ne sont pas modifiés par le code.
Je ne comprends pas très bien comment ça ferait pour ne pas déclencher le trigger sur event ? Dès qu'il y aura un update même partiel il est déclenché, non ? Pour moi les déclenchements des triggers ne coûtent pas trop cher de toute façon, sauf s'ils se mettent à écrire d'autres lignes que celles qu'on est en train de modifier ou font des SELECT un peu complexe.
Mais ça fait une contrib de plus à intégrer.
Le seul cas d'amplification d'écriture qui me parait possible c'est sur le
SET booked_places = ( SELECT COUNT(*) FROM agendas_booking b WHERE b.event_id = e_id AND b.cancellation_datetime IS NULL AND b.in_waiting_list = false ), booked_waiting_list_places = ( SELECT COUNT(*) FROM agendas_booking b WHERE b.event_id = e_id AND b.cancellation_datetime IS NULL AND b.in_waiting_list = true ) WHERE id = e_id;
si vraiment tu veux améliorer ça tu pourrais rajouter une condition au where et utiliser des CTEs:
WITH booked_places AS ( SELECT COUNT(*) AS cnt FROM agendas_booking b WHERE b.event_id = e_id AND b.cancellation_datetime IS NULL AND b.in_waiting_list = false ), booked_waiting_list_places AS ( SELECT COUNT(*) AS cnt FROM agendas_booking b WHERE b.event_id = e_id AND b.cancellation_datetime IS NULL AND b.in_waiting_list = true ) UPDATE agendas_event SET booked_places = booked_places.cnt, booked_waiting_list_places = booked_waiting_list_places.cnt FROM booked_places, booked_waiting_list_places WHERE id = e_id AND (agendas_event.booked_places <> booked_places.cnt OR agendas_event.booked_waiting_list_places <> booked_waiting_list_places.cnt)
Mais vraiment ça ne me parait pas critique (à moins qu'il y ait énormément d'écritures sur les lignes de agendas_booking sans rapport avec les places et les listes d'attente).
Ça me parait donc super mais vu que ça touche quand même à une mécanique complexe je veux bien un autre survol.
Mis à jour par Lauréline Guérin il y a plus de 2 ans
- Fichier 0001-agendas-trigger-full-and-places-event-fields-54747.patch 0001-agendas-trigger-full-and-places-event-fields-54747.patch ajouté
- Statut changé de Solution validée à Solution proposée
Amélioration des triggers (CTE et SELECT INTO)
Je ne comprends pas très bien comment ça ferait pour ne pas déclencher le trigger sur event ?
Si on a la garantie que les champs booked_places, booked_waiting_list_places, full et almost_full ne sont jamais écrasés par chrono, alors on peut se passer du recalcul des compteurs places dans la fonction update_event_full_fields
On peut aussi conditionner le déclenchement de update_event_full_fields_trigger aux changements de valeur de booked_places, booked_waiting_list_places, places et waiting_list_places seulement.
Et le déclenchement de update_event_places_fields_trigger à update avec changement de valeur de in_waiting_list ou cancellation_datetime, insert et delete seulement.
Je ne pense pas non plus qu'il y ait tant de mouvements que cela sur les tables event et booking. Je préfère éviter d'introduire une nouvelle dépendance pour le moment.
si vraiment tu veux améliorer ça tu pourrais rajouter une condition au where et utiliser des CTEs
J'ai fait ça, au moins pour éviter de déclencher update_event_full_fields_trigger sur l'anonymisation des réservations.
Mis à jour par Benjamin Dauvergne il y a plus de 2 ans
- Statut changé de Solution proposée à Solution validée
Toujours ok pour moi.
Mis à jour par Frédéric Péters il y a plus de 2 ans
Sur l'SQL en lui-même je n'ai pas de commentaire mais sur la structure du projet je me demande si ce code pourrait être posé différemment que dans une longue chaine, on pourrait peut-être avoir le code dans un chrono/agendas/sql/update_event_triggers.sql, ou autre nom ou emplacement, il y a peut-être déjà des pratiques existantes. Ça permettrait déjà d'y avoir une coloration syntaxique.
Mis à jour par Lauréline Guérin il y a plus de 2 ans
- Fichier 0001-agendas-trigger-full-and-places-event-fields-54747.patch 0001-agendas-trigger-full-and-places-event-fields-54747.patch ajouté
- Statut changé de Solution validée à Solution proposée
j'ai laissé le sql revert dans la migration (peu de lignes)
Mis à jour par Valentin Deniaud il y a plus de 2 ans
- Statut changé de Solution proposée à Solution validée
Mis à jour par Lauréline Guérin il y a plus de 2 ans
- Statut changé de Solution validée à Résolu (à déployer)
commit 0b53360c0c5eaa08c5d3ec0339e430e106d340d9 Author: Lauréline Guérin <zebuline@entrouvert.com> Date: Mon Aug 16 15:59:01 2021 +0200 agendas: trigger full and places event fields (#54747)
Mis à jour par Frédéric Péters il y a plus de 2 ans
- Statut changé de Résolu (à déployer) à Solution déployée
agendas: trigger full and places event fields (#54747)