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
Index: inc/ticket.class.php
===================================================================
--- inc/ticket.class.php	(revision 1993)
+++ inc/ticket.class.php	(revision 1994)
@@ -424,10 +424,7 @@
                                              " `itemtype` = '".$item->getType()."'
                                                 AND `items_id` = '".$item->getID()."'");
                   // Linked items
-                  if ($subquery = $item->getSelectLinkedItem()) {
-                     $nb += countElementsInTable('glpi_tickets',
-                                                 "(`itemtype`,`items_id`) IN (" . $subquery . ")");
-                  }
+                  $nb += $item->getNumberOfTicketLinked();
                   break;
             }
          } // glpishow_count_on_tabs
Index: inc/commondbtm.class.php
===================================================================
--- inc/commondbtm.class.php	(revision 1993)
+++ inc/commondbtm.class.php	(revision 1994)
@@ -2294,7 +2294,24 @@
       return '';
    }
 
+   /**
+    * Return the number of ticket linked to this printer through a computer
+    *
+    * @return number of ticket
+    */
+   function getNumberOfTicketLinked() {
+      global $DB;
 
+      $query = "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 = '".$this->fields['id']."' AND gci.itemtype='".$this->getType()."'";
+      $res = $DB->query($query);
+      $row = $DB->fetch_assoc($res);
+      return $row['cpt'];
+   }
+
+
    /**
     * Return a field Value if exists
     *
_______________________________________________
Glpi-dev mailing list
Glpi-dev@gna.org
https://mail.gna.org/listinfo/glpi-dev

Reply via email to