Notre Dolibarr ne gère qu’une seule entité.
Je remarque que dans toutes les requêtes sql (ou presque) on recherche les données pour l’entité sélectionnée. (… IN entity IN (1))
Pour une requête du type
SELECT MAX(te.id) FROM llx_actioncomm as te WHERE te.id < ‹ 1715620 › AND te.entity IN (1)
Le temps de réponse est de plus d’une seconde, alors que la requête
SELECT MAX(te.id) FROM llx_actioncomm as te WHERE te.id < ‹ 1715620 ›
est immédiate.
Est-il possible d’avoir un flag global qui permettrait de na pas ajouter « AND entity IN (1) » pour une installation mono entity ?
Dolibarr a pris la décision d’aller vers la possibilité du multi-société, donc toutes les requêtes sont adaptées ou vont l’être. Cette évolution est souhaitable pour beaucoup d’utilisateurs.
Après, on est dans du logiciel libre, donc si vous présentez une évolution de code, documenté sur GitHub ça peut passer !
Par contre, qu’il y ai une très grosse différence de performance entre ces deux requêtes n’est pas normal => Vous devez avoir un problème sur votre installation !
Vous pouvez effectivement avoir une grosse différence de performance dans ce cas.
La requête sans le IN (1) ne doit même pas nécessiter d’interroger la table, le résultat devrait se trouver directement dans l’index. L’autre requête va nécessiter l’utilisation d’un WHERE sur la table ce qui va dégrader les performances.
Si vous lancez vos requêtes en les préfixant avec EXPLAIN vous aurez plus de détails sur la manière dont les requêtes sont executées.
mysql> explain SELECT MAX(te.id) FROM llx_actioncomm as te WHERE te.id < '1720110' AND te.entity IN (1);
+----+-------------+-------+------------+-------+---------------------------+---------+---------+------+--------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+-------+---------------------------+---------+---------+------+--------+----------+-------------+
| 1 | SIMPLE | te | NULL | range | PRIMARY,uk_actioncomm_ref | PRIMARY | 4 | NULL | 624310 | 10.00 | Using where |
+----+-------------+-------+------------+-------+---------------------------+---------+---------+------+--------+----------+-------------+
Donc mon idée de mettre une variable globale pour ne pas ajouter where entity in(1) dans le cas d’un mono site a du sens ?
Si oui, on peut effectuer les modifications
Bonjour,
en fait il me semblerait assez « futé » de faire un remplacement de
$sql .= ' AND entity in ('.getEntity('accounting_account', 0).')';
par $sql .= andEntity();
et la fonction andEntity() ferait le test si multientité ou pas et retournerait donc du code sql ou pas
mais c’est bien plus délicat pour les endroits où on a des « AND / OR » qui vont s’enquiller dans la requête, on souffre alors d’absence d’une couche d’ORM avancée …
exemple
$sql .= ' WHERE p.entity IN ('.getEntity('product').')';
if (strlen(trim($search_current_account))) {
$sql .= natural_search((empty($conf->global->MAIN_PRODUCT_PERENTITY_SHARED) ? "p." : "ppe.") . $accountancy_field_name, $search_current_account);
}
if ($search_current_account_valid == 'withoutvalidaccount') {
$sql .= " AND aa.account_number IS NULL";
}
if ($search_current_account_valid == 'withvalidaccount') {
$sql .= " AND aa.account_number IS NOT NULL";
}
dans ce cas on pourrait avoir un « where » qui serait « vide », nous pourrions alors adopter une « astuce » qui consiste à systématiquement avoir « WHERE 1=1 » puis sql .= andEntity() …
bref c’est un sujet qui pourrait tout a fait être abordé mais d’une manière générale comme le dit @ksar la demande globale est plutôt d’être « multicompany » natif …
Ce n’est pas si simple. Vous avez une différence de performance sur cette requête car elle est très simple, et que dans le cas le plus simple elle va pouvoir renvoyer un résultat directement depuis l’index de la table. Ce cas n’est réellement possible que pour des requêtes très simples, surtout avec InnoDB.
Cela ne signifie absolument pas que vous allez avoir une différence de performance sur les requêtes plus complexes qui permettent à Dolibarr de fonctionner.
L’idée de supprimer le filtre sur entité peut poser de grave problème. En effet, le module peut avoir été activé temporairement puis désactivé. Il faut rester limiter à son entité.
Par contre l’exemple que tu as donné est assez étrange. Tu as mis:
SELECT MAX(te.id) FROM llx_actioncomm as te WHERE te.id < ‹ 1720110 › AND te.entity IN (1);
Hors tu devrais avoir
SELECT MAX(te.id) FROM llx_actioncomm as te WHERE te.id < 1720110 AND te.entity IN (1);
Les simples quotes qui transforme le format en chaine peut avoir un effet sur le plan d’execution.
En quelle version de dolibarr est tu ?
Peux tu refaire le explain plan pour ces 2 requetes APRES avoir mis à jour les stats de la base par
ANALYZE TABLE llx_actioncomm;
explain SELECT MAX(te.id) FROM llx_actioncomm as te WHERE te.id < 1720110 AND te.entity IN (1);
explain SELECT MAX(te.id) FROM llx_actioncomm as te WHERE te.id < 1720110 AND te.entity = 1;
Ayant une idée de la réponse,j’anticipe en donnant une astuce qui peut fonctionner et régler le pb sans aucun dev: Ajoute simplement cet index:
CREATE INDEX idx_actioncomm_entity_id ON llx_actioncomm(entity, id);
Puis refaire à nouveau le explain plan et la mesure de perf. Tu devrais avoir les memes perf que si tu n’avais pas mis le filtre sur entity.
Je ne pense pas. Pas pour l’instant. Il y a encore une anomalie dans l’échange que je ne comprend pas.
L’index devrait être utile si il est combiné mais pas seul. Et je n’arrive pas à reproduire la lenteur, mais sans index.