Bonjour,

je viens de créer un ticket pour traitement de ce problème :
https://forge.indepnet.net/issues/4728

merci pour le retour et pour le patch que nous analyserons pour voir si c'est la meilleure solution.

Cordialement,

Julien Dombre

Le 17/12/2013 15:25, Regis Damongeot a écrit :
Bonjour,

Nous utilisons GLPI sur une base très grosse (plus de 1,5 millions de tickets / 30 000 ordinateurs) et nous avons constaté des performances très mauvaises au fur et à mesure du temps lors de l'ouverture d'un élément d'inventaire (imprimante, moniteur, ...). Récemment le temps d'ouverture d'une fiche d'un de ces éléments pouvait dépasser les 30 secondes sur une machine solide ( quad core / 8go de RAM / disque SSD hébergeant la base MySQL 5 / Linux).

Le problème a rapidement été identifié grâce au mode debug de GLPI : une unique requête était responsable de ces temps de chargement.

Après analyse du code, si je ne me trompe pas, cette requête sert uniquement à compter le nombre de tickets liés à un élément d'inventaire lorsque celui-ci est relié à un ordinateur lui même relié à un ticket. (ticket => ordinateur => élément X, alors indice incrémenté de 1 sur la fiche de cet élément pour l'onglet "Ticket").

Cette requête, pour une imprimante par exemple, est de la forme suivante :
SELECT COUNT(*) AS cpt
FROM `glpi_tickets`
WHERE (`itemtype`,`items_id`) IN (SELECT 'Computer', `computers_id`
  FROM `glpi_computers_items`
  WHERE `itemtype` = 'Printer' AND `items_id` = '13282');

Je comprends bien l'avantage d'un point de vue code pour l'utilisation d'une sous requête (la classe Printer renvoie le bout de requête qui indique quels sont ses liens) mais d'un point de vue MySQL les performances sont catastrophiques : pour les 1,5 millions de tickets en base, il exécute la sous requête autant de fois pour voir quel(s) match(s) il y a (c'est ma supposition, mais vu les temps de réponse ça semble coller). Alors que le pire est que la sous requête ne renvoie aucun résultat (l'imprimante n'est relié à aucun ordinateur).

En reformulant la requête en :
SELECT COUNT(*) AS cpt
FROM `glpi_tickets` gt
LEFT JOIN glpi_computers_items gci ON ( gci.computers_id = gt.items_id)
WHERE gt.itemtype = 'Computer' AND gci.items_id = 13282 AND gci.itemtype='Printer';

On passe à un temps d'exécution nul pour un résultat (si je ne me trompe pas) identique.

À partir de là j'ai modifié le code de GLPI pour utiliser cette requête : j'ai ajouté une nouvelle fonction à la classe commondbtm qui compte le nombre de tickets liés à l'élément (la fonction initiale n'étant visiblement que utilisée à cette fin et non pour voir les liens avec d'autres éléments que les ordinateurs).

Je n'ai appliquée l'optimisation qu'a la classe ticket, mon installation n'utilisant pas les "problèmes", mais je suppose que les lenteurs seraient reproductibles pour les problèmes si ma base en avait beaucoup. Il suffirait dans ce cas d'utiliser la même solution en appelant la nouvelle fonction.

Pour exemple voici les résultats avant et après application du patch:
https://cloud.dedikewl.fr/public.php?service=files&t=3299aea891f8cfdd61a8991556bca2e1 https://cloud.dedikewl.fr/public.php?service=files&t=61fe2bdbceee92393e7c6ea0bf0a8e75

Le patch est pour la version 0.83 mais je l'ai testé sur la 0.84 et il semble fonctionner parfaitement aussi.

Est-ce que j'ai raté quelque chose au niveau de l'analyse/correction du problème ou bien cette optimisation est correcte ?

Cordialement

Régis Damongeot

_______________________________________________
Glpi-dev mailing list
Glpi-dev@gna.org
https://mail.gna.org/listinfo/glpi-dev

Reply via email to