— ## 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 ?
- Schema très indexé (plus de 130 tables).
- Multiples requêtes reads‑heavy (listes de fiches clients, articles, mouvements de stocks).
- Écriture modérée, mais parfois critique lors de la synchronisation multi‑site.
- Gestion d’historique (classe
llxObject), avec des tables d’llxsouvent sujettes à de gros réglages deAUTOINCREMENT.
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_sizepermet 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=0ré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 :
- Créer des index sur les
WHEREfréquemment utilisés (status,type,date_event). - Utiliser des index composés lorsqu’une requête filtre sur plusieurs colonnes (
client_id,type) :
- Créer des index sur les
ALTER TABLE llx_client ADD INDEX idx_client_status (status, id);
- Drop les index inutiles (ex. index sur
createurqui 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 tablellx_categorietrè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
SELECTles 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
-
É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é).
-
É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.
- 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 :
- Mesurable (via des métriques précises).
- Justifiable par le ROI (gain de temps, économies d’infrastructure, augmentation du CA).
- 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.