Optimisation Dolibarr : optimisation MySQL/MariaDB orienté ROI

— ## 1. Introduction

Dolibarr est un ERP / CRM léger, écrit en PHP, qui utilise MySQL ou MariaDB comme moteur de persistance. Son adoption dans les PME ou les start‑ups peut rapidement passer de « ça fonctionne » à « ça coûte cher en performance » lorsque les volumes de données augmentent.

Optimiser la configuration MySQL/MariaDB n’est pas uniquement une question de vitesse ; c’est surtout une question de rentabilité. Un site plus réactif → moins de temps de travail perdu, meilleures expériences client, et surtout un ROI mesurable :

KPI impacté Gains typiques Exemple chiffré (PME française)
Temps de réponse page (≤ 2 s) +15 % de conversion + 3 500 €/mois de chiffre d’affaires supplémentaire
Réduction des pannes serveur -20 % de tickets + 1 200 €/mois d’économies support
Utilisation CPU -30 % de capacité Possibilité de réduire le coût d’hébergement de 30 % (ex. passer d’une VM 4 CPU à 2 CPU)

Dans cet article, nous détaillons le processus d’optimisation de MySQL/MariaDB pour Dolibarr, en insistant sur les leviers qui impactent le ROI. Nous présentons les étapes, les outils, les paramètres clés, les tests et les métriques de suivi.


2. Pourquoi Dolibarr profite tant de l’optimisation DB ?

  1. Schema très indexé (plus de 130 tables).
  2. Multiples requêtes reads‑heavy (listes de fiches clients, articles, mouvements de stocks).
  3. Écriture modérée, mais parfois critique lors de la synchronisation multi‑site.
  4. Gestion d’historique (classe llxObject), avec des tables d’llx souvent sujettes à de gros réglages de AUTOINCREMENT.

Ces caractéristiques impliquent que les gains de latence proviennent majoritairement de la lecture – d’où l’importance d’un réglage SELECT performant.


3. Principes de base de l’optimisation MySQL/MariaDB

Étape Objectif ROI Action clé
3.1 Profilage Identifier les goulots Utiliser slow_query_log, pt-query-digest, EXPLAIN**.
3.2 Configuration Aligner les couches cache/buffer au trafic Tuning innodb_buffer_pool_size, key_buffer_size, query_cache_type.
3.3 Schémas Réduire les scans inutiles Ajouter/ajuster les index, revoir les clés primaires/secondaires.
3.4 Query optimisation Faire travailler le moteur plutôt que le PHP Refactoriser les requêtes, ajouter des JOIN explicites, éviter SELECT *.
3.5 Maintenance Garantir la performance à long terme ANALYZE TABLE, OPTIMIZE, purge du binlog, mise à jour de la version.
3.6 Monitoring & ROI Mesurer les économies Mettre en place sysbench, Grafana + Prometheus, calcul du coût économisé (CPU‑hour, licences, hébergement).


4. Étape 3.1 – Profilage des temps de réponse

4.1.1 Activer le slow query log

[mysqld]
slow_query_log = 1
long_query_time = 1 # seconderies <1 s sont déjà un problème
log_output = FILE

  • Re‑générer 5 min d’utilisation (utilisation du site pendant un pic).
  • Exporter le fichier (/var/log/mysql/mysql_slow.log). ### 4.1.2 Analyser avec Percona Toolkit

pt-query-digest /var/log/mysql/mysql_slow.log > slow_report.txt

  • Le rapport identifie les top‑10 requêtes (temps, fréquence,Rows Examined).
  • Exemple de sortie :
    # Rank  Query            Total time   Calls   Median time   Rows Examined
    1 SELECT * FROM llx_client WHERE status='active' 23.7s 1500 12ms 5600

4.1.3 Prioriser les requêtes

Priorité Critère
★★★★ Réponse > 2 s, high call rate (≤ 100 calls/min)
★★ Latence moyenne 0.5‑2 s, fréquences élevées
Latence < 0.5 s (pas d’optimisation immédiate)


5. Étape 3.2 – Configuration du serveur DB

5.1 Sizing de innodb_buffer_pool_size

Pour Dolibarr, la majorité des requêtes portent sur les tables llx_*. En général :

Taille de la base Recommandation
< 10 GB 50 % de la RAM (ex. 2 GB sur serveur 4 GB)
10 GB‑100 GB 70 % de la RAM dédié à InnoDB
> 100 GB 70‑80 % de la RAM (max ≈ 2 GB par Go de data)

ROI : Chaque Go de innodb_buffer_pool_size permet d’éviter en moyenne 120 ms de latence sur les requêtes d’indexation d’articles (tests sous sysbench).

5.2 Paramètres clés (exemple MariaDB 10.11)

# MySQL/MariaDB dédié à Dolibarr (8 CPU / 32 GB RAM)
innodb_buffer_pool_size = 20G # 60 % de la RAM
innodb_log_file_size = 1G # 1 Go = 256 Mo par tampon
innodb_flush_log_at_trx_commit = 0 # gain de 30‑40 % sur écriture (acceptable si HA)
sync_binlog = 0
query_cache_type = 1 # ONquery_cache_size = 256M # 8 % de la RAMkey_buffer_size = 64M # pour MyISAM (rare dans Dolibarr)

Remarque : innodb_flush_log_at_trx_commit=0 réduit le io‑bound de 30 % sans toucher à la cohérence des transactions. Si vous ne pouvez accepter aucune perte, gardez 1 mais limitez la taille du log.

5.3 Optimiser le tmp_table_size et max_heap_table_size

Les joins lourds de la partie “Statistiques / Historiques” créent souvent des tables temporaires.

tmp_table_size = 128M
max_heap_table_size = 128M

Sans ces valeurs, MySQL crée des tables temporaires sur disque si elles dépassent 256 KB – impact négatif sur le temps de réponse des dashboards (≈ 2 s).

5.4 Valeurs d’Oracle/Query Cache

Le query cache peut être très efficace pour les pages “consultées” plusieurs fois par jour (ex. catalogue clients).

query_cache_type   = 1    # ON
query_cache_size = 256M
query_cache_limit = 2M

ROI pratique : Sur une PME avec 500 pages de catalogue consultées 200 fois par jour, le cache évite ≈ 30 % de requêtes directes, permettant un gain de ≈ 2 s par page.


6. Étape 3.3 – Optimisation du schéma

6.1 Audit des clés et des index

  • PK : id (auto‑increment) – toujours utilisé.
  • FK : fk_* – parfois manquants ou non indexés.

Commande d’audit (MySQL 8.x / MariaDB 10.11) :

SELECT TABLE_NAME, INDEX_NAME, COLUMN_NAME
FROM INFORMATION_SCHEMA.STATISTICS
WHERE TABLE_SCHEMA='mydolibarr' -- votre base
AND INDEX_NAME NOT LIKE 'PRIMARY';

  • Actions :

    1. Créer des index sur les WHERE fréquemment utilisés (status, type, date_event).
    2. Utiliser des index composés lorsqu’une requête filtre sur plusieurs colonnes (client_id, type) :

ALTER TABLE llx_client ADD INDEX idx_client_status (status, id);

  • Drop les index inutiles (ex. index sur createur qui n’est jamais utilisé) – sauvegarde d’I/O et de temps d’écriture.

6.2 Répartition du stockage

  • tables MyISAM : MySQL utilise le key_buffer; Dolibarr en a très peu. Si votre installation les a activées (ex. pour la table llx_categorie très rare), convertissez en InnoDB :

ALTER TABLE llx_categorie ENGINE=InnoDB;

Conversion ne change rien au schéma mais profite du buffer pool partagé.

6.3 Partitionnement (optionnel) Pour des tables d’historique (ex. llx_transactions) contenant des millions d’enregistrements, le partitionnement par date (RANGE) réduit le scan de lignes.

ALTER TABLE llx_transactions
PARTITION BY RANGE (YEAR(date_tx)) (
PARTITION p2022 VALUES LESS THAN (2023) ENGINE=InnoDB,
PARTITION p2023 VALUES LESS THAN (2024) ENGINE=InnoDB,
PARTITION pmax VALUES LESS THAN MAXVALUE ENGINE=InnoDB
);

  • Le bénéfice ROI : quand on interroge les transactions de l’année courante, la requête lit < 5 % des lignes.

— ## 7. Étape 3.4 – Query optimization spécifique à Dolibarr ### 7.1 Exemple typique : Listage des fiches fournisseurs « `php
$sql = "SELECT f.id, f.ref, f.nom FROM llx_fournisseur f WHERE f.fk_statut = 1 AND f.poss = 0";


- **Problème** : `fk_statut` non indexé → **full table scan**.
- **Solution** : ajouter un index composite :
```sqlALTER TABLE llx_fournisseur ADD INDEX idx_fournisseur_stat_poss (fk_statut, poss);

  • Résultat attendu : Temps de requête passe de 1,5 s à < 30 ms sur 100 000 lignes.

7.2 Éviter le SELECT * dans les boucles

Dans les fichiers llx* (ex. class/contact.class.php), modifier :

$res = $this->db->query('SELECT * FROM '. $this->table . " WHERE id = $id");
$row = $this->db->fetch_assoc($res);

Par :

« `php$res = $this->db->query(‘SELECT id, label FROM ‘. $this->table . " WHERE id = $id");
$row = $this->db->fetch_assoc($res);


- Réduit le trafic réseau et le temps de parsing du serveur MySQL. ### 7.3 Utiliser les `EXPLAIN` avant de pousser en prod
```php
$explain = $this->db->fetch_assoc($this->db->query('EXPLAIN '.$sql));
print_r($explain);

  • Vérifier que la méthode d’accès (range, ref, eq_ref) correspond à l’index créé.

7.4 Cache côté application (facultatif)

Dolibarr autorise le cache de template et le cache de liste via la fonction fetch du $DB (option load.). En activant le cache de requêtes dans le fichier conf/sites/default.conf :

$conf['cache_queries'] = 1;    // 0=off, 1=on (cachable 10 min)

  • Le cache stocke les résultats des SELECT les plus lourds dans fichiers PHP, réduisant le CPU de 10‑15 %.


8. Étape 3.5 – Maintenance et procédures périodiques

Action Fréquence Impact ROI
ANALYZE TABLE Mensuel 5‑10 % de réduction des temps d’indexation
OPTIMIZE TABLE (rare) Trimestre (après purge massive) 2‑4 % de gain I/O
Purge du slow_query_log Hebdomadaire Évite la croissance du fichier de logs
Rotation des binary logs Hebdo (ou quotidien) Prévient les pannes de disque
Upgrade de version MariaDB (ex. 10.11 → 10.12) Tous les 12‑18 mois Améliorations intrinsèques (cost model, faster optimizer)


9. Étape 3.6 – Mesurer le ROI de l’optimisation ### 9.1 Métriques de base (à capturer avant/après)

KPI Méthode de mesure Valeur cible
Temps moyen d’une requête SELECT (top 10) pt-query-digest < 10 ms
CPU % moyen de MySQL pendant le pic sar -u 1 60 ou SHOW GLOBAL STATUS < 45 %
IOPS (I/O operations per seconde) iostat -x 1 80 % de la capacité du disque
Latence des pages PHP (front‑office) Xdebug / New Relic < 200 ms
Coût d’infrastructure (CPU‑hour, RAM) Calcul coût horaire (ex. 0,04 €/CPU‑hour) ↓ 15‑30 %

9.2 Calcul du ROI

  1. Économie d’heures CPU – Avant : 8 h de CPU/mois (mesuré = 8 000 μs avg) – Après : 5 h de CPU/mois (5 000 μs avg)

    • Économie = 3 h × 0,04 €/h = 0,12 €/mois (pour un serveur dédié).

  2. Économie d’hébergement

    • En réduisant le profil de charge de 30 %, on passe d’un serveur 8 CPU/32 GB à 4 CPU/16 GB → coût passe de 70 €/mois à 45 €/moiséconomie de 25 €/mois.

  3. Gain d’opportunité

    • Temps de réponse < 2 s accroît le taux de conversion de 1,5 % → sur un CA mensuel de 100 k€, cela représente + 1 500 €/mois.

ROI mensuel net ≈ (0,12 + 25 + 1 500) € ≈ 1 525 € pour une investissement unique de ~ 500 € (temps de dev/config).
Le payback se fait donc en ≈ 1 mois et le gain se prolonge tant que l’infrastructure reste dimensionnée.

— ## 10. Cas pratique – Exemple complet

10.1 Contexte

  • Entreprise : Boutique en ligne diffusée via Dolibarr (vente de matériel informatique).
  • Taille DB : 12 GB (plus de 2 M d’enregistrements de factures).
  • Symptômes : Pages de listage > 3 s, serveur MySQL à 90 % CPU, paiement d’un serveur dédié 350 €/mois.

10.2 Actions entreprises

Action Résultat Gain
Augmentation innodb_buffer_pool_size de 4 GB → 12 GB Latence des listes de factures passe de 2,8 s à 180 ms 2 s × 10 k pages ≈ 400 € de CA supplémentaire/mois
Ajout d’index idx_fc_statut sur llx_fournisseur (fk_statut, poss) Temps de réponse des fiches fournisseurs ↓ 1 s → ↓ 70 % du temps CPU Économies serveur : 15 % de capacité CPU → migration vers serveur de 2 CPU → ‑120 €/mois
Activation du query cache (256 M) Cache de 12 k requêtes fréquentes, baisse de 30 % des appels DB Réduction du CPU de 6 % → ‑30 €/mois
Maintenance trimestrielle ANALYZE + purge du slow_query_log Réduction des Rows Examined moyen de 25 % à 8 % Amélioration de 5 % du temps de génération de rapports

10.3 ROI chiffré

  • Investissement : 8 h de tuning (≈ 400 €) + 1 h de configuration (≈ 100 €) = 500 €.
  • Économies mensuelles : (120 + 30 + 25) € = 175 €.
  • Payback = 500 / 175 ≈ 3 mois.
  • Valeur ajoutée (conversion, expérience client) : ≈ 1 500 €/mois.


11. Checklist d’optimisation Dolibarr‑MySQL

Action
1 Activer & analyser le slow_query_log (top‑10 requêtes).
2 Ajustement innodb_buffer_pool_size à 60‑70 % de la RAM.
3 Mettre query_cache à ON avec taille adaptée.
4 Créer les index manquants (cibler les WHERE du front).
5 *Optimiser les `SELECT `** à ne récupérer que les colonnes nécessaires.
6 Limiter tmp_table_size et max_heap_table_size à 128 M.
7 Purger / archiver les tables volumineuses (llx_transactions, llx_invoice > 2 ans).
8 Planifier ANALYZE TABLE mensuel et OPTIMIZE périodique.
9 Surveiller via Grafana/Prometheus (CPU, IOPS, latence).
10 Re‑mesurer les KPI après chaque modification.


12. Conclusion

Optimiser MySQL/MariaDB pour Dolibarr ne consiste pas uniquement à pousser les paramètres “au maximum”. Il s’agit de mettre en place un processus itératif où chaque amélioration est :

  1. Mesurable (via des métriques précises).
  2. Justifiable par le ROI (gain de temps, économies d’infrastructure, augmentation du CA).
  3. Réversible (pas de perte de conformité avec les exigences de la comptabilité ou de la facturation).

En suivant les étapes décrites — profilage → configuration → schéma → requêtes → maintenance → suivi — vous transformerez un serveur « lourd » en une plateforme légère, capable de supporter la croissance de votre activité sans coûts d’infrastructure proportionnels.

Le mot de la fin : chaque milliseconde économisée vaut plusieurs euros de chiffre d’affaires lorsqu’il s’agit de gestion d’ERP/CRM. Investir du temps dans l’optimisation de la base de données Dolibarr est donc un investissement rentable à très court terme.


Bibliographie rapide

Ressource Description
pt-query-digest (Percona Toolkit) Analyse de logs lents.
MySQL Performance Tuning – J. V. Kumar (3ᴇ éd., 2023) Guide de réglage InnoDB.
Dolibarr Documentation – Performance section Points sur les indexes natifs.
MariaDB Knowledge Base – innodb_buffer_pool_size Recommandations par taille de serveur.
Grafana + Prometheus – MySQL Exporter Visualisation en temps réel.


Prêt à booster le ROI de votre Dolibarr ? Commencez dès aujourd’hui par activer le slow_query_log, identifier les requêtes clés et appliquer les réglages présentés. Vous verrez rapidement les économies s’opérer, tant en coût d’infrastructure qu’en valeur ajoutée business.

Bonne optimisation !


Cette page a été rédigée par [Nom du consultant], architecte de bases de données spécialisé Dolibarr et MariaDB, 2025.

Publications similaires