MySQL vs OpenSearch pour la recherche auto-hébergée : utile ou se faire du mal sur un VPS ?

Cet article vous a aidé ?

Vous avez un VPS. Vous avez des utilisateurs qui tapent « invoice 2021 acme » et attendent de la magie. Vous avez aussi un budget d’exploitation qui ressemble dangereusement à « vous, après le dîner ». La question n’est pas de savoir si OpenSearch peut chercher mieux que MySQL. Il le peut. La question est de savoir si le faire tourner vous‑même sur une petite machine est une contrainte intelligente… ou un incident en mode ralenti.

C’est la différence pratique entre « la recherche comme fonctionnalité » et « la recherche comme système distribué toujours actif qui prend personnellement offense du manque de RAM ». Choisissez le mauvais outil et votre VPS vous enseignera l’humilité, une tempête de swap à la fois.

Le cadre de décision : ce que vous choisissez vraiment

Si vous réduisez la décision à « lequel est plus rapide », vous obtiendrez une réponse coûteuse et un système peu fiable. Ce que vous choisissez, c’est :

  • Qualité de recherche vs complexité opérationnelle. MySQL peut fournir une recherche par mots‑clés correcte. OpenSearch permet d’ajuster la pertinence, la tolérance aux fautes de frappe, des analyseurs linguistiques, des synonymes, des facettes, du highlighting, et plus encore. Il exige aussi de la mémoire, des E/S disques et une attention continue.
  • Un système vs deux systèmes de référence. Si vous ajoutez OpenSearch, MySQL reste votre système de référence. Vous avez désormais aussi un index « finalement cohérent ». Il faut concevoir et exploiter la synchronisation.
  • Modes de défaillance. Quand MySQL est lent, ce sont généralement des requêtes, des verrous ou des E/S. Quand OpenSearch est lent, cela peut être la pression du heap, des merges de segments, un turnover du cache, des pauses du GC, la disposition des shards, le comportement de refresh/flush, ou un disque qui ment sur ses performances.
  • Ce que vous pouvez vous permettre d’avoir tort. Sur un petit VPS, une mauvaise hypothèse peut devenir « tout va bien » jusqu’à ce que le noyau tue Java pour manque de mémoire.

Voici un conseil franc :

  • Si votre recherche est simple (mots‑clés titre/contenu, filtres sur quelques colonnes, corpus de taille modérée), commencez par MySQL et pas d’excuses. Utilisez des index appropriés, peut‑être FULLTEXT, et acceptez que la pertinence soit « suffisante ».
  • Si la recherche est une valeur produit centrale (pertinence, tolérance aux fautes, facettes, pondérations multi‑champs, synonymes, langues), utilisez OpenSearch — mais envisagez une offre gérée avant de l’auto‑héberger sur un petit VPS.
  • Si vous tenez quand même à auto‑héberger OpenSearch sur un VPS, faites‑le comme si vous gériez un service de production : surveillance, snapshots, réglage du heap, vérifications disque et plan de reprise testé. Sinon vous n’êtes pas en train d’auto‑héberger ; vous improvisez.

Une citation à afficher au mur de quiconque auto‑héberge la recherche : « Tout échoue tout le temps. »

Faits et historique qui expliquent les douleurs d’aujourd’hui

Un peu de contexte rend les compromis moins arbitraires. Voici des faits concrets et utiles qui se traduisent directement en réalité opérationnelle :

  1. Lucene est le moteur au cœur d’Elasticsearch et d’OpenSearch. Il existe depuis la fin des années 1990, et son modèle de segments/merges explique pourquoi les E/S disque importent tant.
  2. FULLTEXT de MySQL précède les « plateformes de recherche » modernes. Il a été conçu pour ajouter une recherche par mots‑clés aux charges relationnelles, pas pour être un laboratoire de pertinence.
  3. Elasticsearch a commencé en 2010 comme serveur de recherche distribué basé sur Lucene, conçu pour rendre les « clusters de recherche » abordables — jusqu’à ce qu’il faille en assurer l’exploitation.
  4. OpenSearch est un fork d’Elasticsearch 7.10 après des changements de licence. Opérationnellement, il hérite de la plupart des forces et des pièges d’Elasticsearch.
  5. Les index inversés expliquent pourquoi OpenSearch est rapide pour le texte. Ce n’est pas une « base de données qui fait du LIKE » ; c’est une structure de données optimisée pour la récupération.
  6. Le LIKE ‘%terme%’ de MySQL ne peut pas utiliser un index B‑tree normal pour les jokers en tête, ce qui pousse vers des scans de table puis des reproches adressés à « la recherche MySQL ».
  7. Refresh vs commit est un vrai concept dans les systèmes basés sur Lucene. Un document peut être « recherchable » rapidement (refresh) mais pas forcément durable avant un commit/snapshot ultérieur.
  8. Les petits disques de VPS ont souvent des crédits de rafale. Votre benchmark peut sembler excellent jusqu’à épuisement des crédits, puis les merges de segments deviennent de la gadoue.

Pertinence, analyseurs et « pourquoi ça ne trouve pas ? »

Pertinence MySQL : des réglages grossiers

Le scoring FULLTEXT de MySQL existe, mais il n’est pas conçu pour l’ajustement itératif de pertinence que les équipes produit font souvent. Vous pouvez :

  • Faire des requêtes en langage naturel et le mode boolean.
  • Faire des pondérations entre colonnes en fractionnant et combinant les scores (gênant, mais possible).
  • Listes de stopwords et longueur minimale des mots (varie selon le moteur/version).

Le plus grand piège : s’attendre à ce que FULLTEXT de MySQL se comporte comme une recherche web moderne. Ce ne sera pas le cas, et vous perdrez du temps à essayer de le faire semblant.

Pertinence OpenSearch : plus de puissance, plus de responsabilité

OpenSearch vous donne des analyseurs (tokenisation, mise en minuscules, stemming), des mappings par champ, des multi‑fields (keyword + text) et une flexibilité du DSL de requête. Vous pouvez rendre la recherche « intelligente ». Vous pouvez aussi la casser au point qu’elle ne trouve rien parce que l’analyseur ne tokenise pas comme vous l’aviez supposé.

Implication opérationnelle : une erreur de mapping est une panne

Une erreur de mapping dans OpenSearch nécessite souvent de « réindexer le monde ». Sur un VPS, la réindexation peut être ce qui renverse le nœud. Planifiez :

  • Indices versionnés et alias.
  • Jobs de réindexation contrôlés avec limitation de débit.
  • Snapshots avant les gros changements.

Stockage et E/S : le tueur silencieux pour la recherche sur VPS

Sur le papier, MySQL et OpenSearch sont des « systèmes basés disque ». En pratique :

  • MySQL est sensible aux schémas d’E/S aléatoires (le taux de hit du buffer pool compte), au fsync des logs et à la contention avec d’autres charges.
  • OpenSearch est sensible au débit d’écriture soutenu pendant l’indexation et les merges, et à la latence de lecture pendant la charge de requêtes — en plus d’utiliser fortement le cache de pages OS.

Sur un VPS, le disque est souvent le composant le moins honnête. « NVMe » dans la description peut toujours signifier E/S partagées, crédits de rafale, voisins bruyants et throttling. Les merges de segments se moquent de votre argumentaire marketing.

Deuxième blague : Le cloud dit que votre disque fait « jusqu’à 3 000 IOPS ». Mon expérience dit « jusqu’à 3 000 IOPS, brièvement, si la lune approuve ».

Trois mini‑histoires d’entreprise issues du terrain

Incident causé par une mauvaise hypothèse : « la recherche est en lecture seule, donc ça ne touchera pas la prod »

Une équipe SaaS de taille moyenne a ajouté OpenSearch pour la recherche côté client. Ils avaient testé la performance des requêtes en staging et en étaient fiers. La mauvaise hypothèse : le trafic de recherche est « en lecture seule », donc sûr à co‑localiser sur la même instance de type VPS que la base applicative au lancement.

La première semaine s’est bien passée. Puis un client a importé un grand jeu de données et l’équipe a activé l’indexation quasi temps réel : les refreshs sont restés fréquents, l’indexation a tourné en continu et les merges ont commencé à s’empiler. La latence a augmenté, mais pas d’abord sur le point de terminaison de recherche. Elle est apparue partout ailleurs : timeouts d’API, lenteurs de connexion, travaux en arrière‑plan à la traîne.

Le coupable n’était pas le CPU. C’était la contention disque. Le nœud OpenSearch faisait des écritures soutenues plus des merges ; l’instance MySQL (même hôte) tentait de fsync son redo log. Les deux faisaient « correctement ». Ensemble, c’était catastrophique.

La correction fut douloureusement simple : séparer les charges et ajouter une surveillance disque explicite. Ils ont aussi augmenté les intervalles de refresh pendant l’indexation en masse et ajouté un mécanisme de backpressure dans le pipeline d’ingestion.

La leçon : les systèmes « en lecture seule » écrivent encore, parfois agressivement. Surtout la recherche.

Une optimisation qui s’est retournée contre eux : le nombre de shards comme placebo de performance

Un groupe d’ingénierie est passé de FULLTEXT MySQL à OpenSearch pour une meilleure pertinence et des facettes. Les premiers benchmarks étaient mitigés. Quelqu’un a suggéré d’augmenter le nombre de shards pour « paralléliser » les requêtes sur un seul nœud. Ça semblait plausible. C’était faux pour leur cas.

Ils ont pris un index modeste et l’ont fragmenté en nombreux shards. Le débit de requêtes n’a pas augmenté. Au contraire, la pression sur le heap a monté : plus de structures au niveau shard, plus de métadonnées de segments, plus de caches en concurrence. Les pauses GC sont devenues visibles lors des pics de trafic. Le débit d’indexation a diminué parce que les merges se produisaient sur beaucoup de petits shards plutôt que sur quelques shards efficaces.

Ils ont essayé de « corriger » en augmentant le heap. Cela a réduit la fréquence des GC mais augmenté les pauses quand elles surviennent, et affamé le cache de pages OS. Les requêtes ont ralenti à nouveau parce que les lectures disque ont augmenté.

Ils ont récupéré en réindexant vers moins de shards (et en basculant via un alias), en gardant le heap modéré et en laissant de la mémoire pour le cache de pages. L’amélioration n’est pas venue d’un nombre magique ; elle est venue du fait d’arrêter le système de se battre lui‑même.

La leçon : le nombre de shards n’est pas un bouton de performance. C’est une décision de distribution des données avec des conséquences opérationnelles.

Une pratique ennuyeuse mais correcte qui a sauvé la mise : snapshots et exercices de restauration

Une entreprise faisait tourner OpenSearch en service auto‑hébergé nœud unique pour la recherche de logs interne et une petite fonctionnalité de recherche client. Pas glamour. Ils avaient une habitude disciplinée : des exercices hebdomadaires de restauration de snapshots sur une instance scratch. Personne n’aimait le faire. C’était un élément de checklist qui semblait toujours inférieur à « vrai travail ».

Un jour, après un patch OS et un reboot, le nœud est revenu avec un problème de système de fichiers qui a corrompu une partie du magasin d’index. OpenSearch a refusé de démarrer proprement. L’équipe n’a pas débattu en théorie pendant des heures. Ils ont déclaré le nœud non sain, provisionné une nouvelle instance, installé la même version d’OpenSearch et restauré le dernier snapshot.

Ils ont encore eu une fenêtre d’indisponibilité, mais elle a été mesurée et prévisible plutôt que panique ouverte. La qualité de recherche est restée intacte parce que leur exercice de restauration validait les mappings, templates et le processus de récupération end‑to‑end.

La leçon : des snapshots sans exercices de restauration ne sont que de la pensée positive. La pratique ennuyeuse transforme une « perte de données » en « après‑midi agaçant ».

Mode d’emploi pour un diagnostic rapide

Quand « la recherche est lente », il faut répondre vite à une question : est‑ce CPU, mémoire, disque ou conception des requêtes ? Voici une séquence qui fonctionne dans la vraie vie.

Première étape : l’hôte est‑il en train de mourir ?

  • Vérifiez la charge, le CPU steal (VPS !), la pression mémoire, le swap et la saturation disque.
  • Si l’hôte est malade, ne commencez pas à tuner les requêtes. Corrigez le goulot d’étranglement plateforme.

Deuxième : le service est‑il stable ?

  • MySQL : connexions, threads, requêtes lentes, état InnoDB, comportement du buffer pool.
  • OpenSearch : santé du cluster (même en nœud unique), pression heap JVM, pauses GC, pools de threads, requêtes rejetées.

Troisième : est‑ce un problème d’indexation/refresh/merge ?

  • OpenSearch : vérifiez le débit d’indexation, l’intervalle de refresh, les merges et le translog.
  • MySQL : vérifiez l’amplification d’écriture, le fsync et le taux de hit du buffer pool.

Quatrième : est‑ce la requête ?

  • MySQL : EXPLAIN, indexes, scans complets, tables temporaires, filesorts.
  • OpenSearch : profilez les requêtes, analysez la tokenisation, inspectez les mappings et validez le DSL.

Cinquième : décider de la contention

  • Réduire le rayon d’impact : limiter l’indexation, augmenter l’intervalle de refresh, désactiver les agrégations coûteuses, plafonner la complexité des requêtes, ou dégrader temporairement des fonctionnalités.
  • Puis corriger la cause racine.

Tâches pratiques : commandes, sorties, décisions (12+)

Voici de vraies commandes que vous pouvez exécuter sur un Linux VPS typique avec MySQL et/ou OpenSearch. Chaque item inclut ce que la sortie signifie et la décision suivante.

1) Vérifier le CPU steal et la charge (réalité VPS)

cr0x@server:~$ mpstat -P ALL 1 3
Linux 6.5.0 (server)  12/30/2025  _x86_64_  (2 CPU)

12:01:00 PM  CPU   %usr %nice  %sys %iowait %irq %soft %steal %idle
12:01:01 PM  all   22.00  0.00  8.00   3.00 0.00  1.00  18.00 48.00

Signification : %steal à 18% signifie que votre hyperviseur vous prend du CPU. Ce n’est pas « votre appli est lente », c’est « votre VPS est sur‑vendu ».

Décision : Si %steal est constamment >5–10% pendant les incidents, upgradez/déplacez l’hôte avant de faire des micro‑optimisations.

2) Vérifier la pression mémoire et l’utilisation du swap

cr0x@server:~$ free -h
               total        used        free      shared  buff/cache   available
Mem:           3.8Gi       3.3Gi       120Mi        42Mi       420Mi       180Mi
Swap:          2.0Gi       1.6Gi       400Mi

Signification : Vous swappez fortement. OpenSearch + swap est une tragédie lente ; MySQL + swap est aussi mauvais, mais plus discret.

Décision : Réduisez le heap OpenSearch, réduisez la charge, ajoutez de la RAM ou déplacez la recherche hors‑site. Si le swap est non nul en état stable, vous avez un problème d’exploitation.

3) Vérifier la latence et la saturation disque

cr0x@server:~$ iostat -xz 1 3
Linux 6.5.0 (server)  12/30/2025  _x86_64_  (2 CPU)

Device            r/s     w/s   rMB/s   wMB/s  await  %util
nvme0n1          55.0   220.0    2.1    18.4  42.30  97.00

Signification : 97% d’utilisation et 42 ms d’attente signifie que le disque est le goulot. Les nœuds de recherche détestent ça ; MySQL aussi.

Décision : Limitez l’indexation/les merges (OpenSearch), baissez le taux d’écriture (les deux), passez à un stockage plus performant ou séparez les services.

4) Vérifier l’espace disque et la pression inode

cr0x@server:~$ df -h /var/lib
Filesystem      Size  Used Avail Use% Mounted on
/dev/vda1        80G   74G  2.1G  98% /

Signification : 98% d’occupation est en territoire incident. OpenSearch a besoin d’espace libre pour les merges ; MySQL a besoin d’espace pour les logs et les tables temporaires.

Décision : Libérez de l’espace maintenant. Si OpenSearch est présent, assurez‑vous d’avoir suffisamment d’espace libre avant une indexation ou une réindexation lourde.

5) Vérifier les événements OOM au niveau noyau

cr0x@server:~$ journalctl -k -S -2h | tail -n 8
Dec 30 10:55:12 server kernel: Out of memory: Killed process 1920 (java) total-vm:6123456kB, anon-rss:2567890kB
Dec 30 10:55:12 server kernel: oom_reaper: reaped process 1920 (java), now anon-rss:0kB, file-rss:0kB

Signification : Le noyau a tué OpenSearch (Java). Ce n’est pas un bug applicatif ; c’est une question de capacité/limites.

Décision : Réduisez le heap, désactivez les fonctionnalités gourmandes en mémoire, migrez vers un nœud plus grand, ou arrêtez d’auto‑héberger la recherche sur ce VPS.

6) Vérifier que MySQL utilise bien des index (et pas l’espoir)

cr0x@server:~$ mysql -e "EXPLAIN SELECT id,title FROM posts WHERE title LIKE '%invoice%' ORDER BY created_at DESC LIMIT 20\G"
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: posts
   partitions: NULL
         type: ALL
possible_keys: idx_title,idx_created_at
          key: NULL
      key_len: NULL
          ref: NULL
         rows: 184233
     filtered: 10.00
        Extra: Using where; Using filesort

Signification : type: ALL et key: NULL signifie un scan complet de table. LIKE avec un joker en tête n’utilisera pas un index normal.

Décision : Redessinez la requête (recherche par préfixe), ajoutez FULLTEXT, ou acceptez qu’il vous faille un moteur de recherche.

7) Vérifier le statut du slow query log MySQL (et s’il ment)

cr0x@server:~$ mysql -e "SHOW VARIABLES LIKE 'slow_query_log%'; SHOW VARIABLES LIKE 'long_query_time';"
+---------------------+-------+
| Variable_name       | Value |
+---------------------+-------+
| slow_query_log      | ON    |
| slow_query_log_file | /var/log/mysql/mysql-slow.log |
+---------------------+-------+
+-----------------+-------+
| Variable_name   | Value |
+-----------------+-------+
| long_query_time | 1.000 |
+-----------------+-------+

Signification : Le slow log est activé avec un seuil à 1s. Bien : vous pouvez observer la réalité.

Décision : Si le slow log est désactivé en production, activez‑le (prudemment) et commencez à mesurer avant de réécrire des systèmes.

8) Inspecter la pression InnoDB et le comportement du buffer pool

cr0x@server:~$ mysql -e "SHOW ENGINE INNODB STATUS\G" | sed -n '1,40p'
=====================================
2025-12-30 12:05:01 INNODB MONITOR OUTPUT
=====================================
BUFFER POOL AND MEMORY
Total large memory allocated 2147483648
Buffer pool size   131072
Free buffers       8
Database pages     130000
Modified db pages  5200

Signification : Presque aucun buffer libre, beaucoup de pages modifiées. Sous charge d’écriture, le flushing peut dominer la latence.

Décision : Si le disque est saturé, réduisez le taux d’écriture, ajustez le flushing, ou déplacez la charge de recherche hors de MySQL.

9) Vérifier la santé du cluster OpenSearch (un nœud unique a besoin d’un statut pas trop triste)

cr0x@server:~$ curl -s localhost:9200/_cluster/health?pretty
{
  "cluster_name" : "vps-search",
  "status" : "yellow",
  "timed_out" : false,
  "number_of_nodes" : 1,
  "number_of_data_nodes" : 1,
  "active_primary_shards" : 12,
  "active_shards" : 12,
  "unassigned_shards" : 12
}

Signification : Yellow sur un nœud unique signifie généralement que des replicas sont non assignés (il n’y a nulle part où les mettre).

Décision : Sur un nœud unique, mettez les replicas à 0 pour les indices où vous acceptez l’absence de redondance, et compensez par des snapshots.

10) Vérifier la pression du heap JVM OpenSearch

cr0x@server:~$ curl -s localhost:9200/_nodes/stats/jvm?pretty | sed -n '1,40p'
{
  "nodes" : {
    "Q1" : {
      "jvm" : {
        "mem" : {
          "heap_used_in_bytes" : 1638000000,
          "heap_max_in_bytes" : 2147483648
        }
      }
    }
  }
}

Signification : ~76% du heap utilisé. C’est acceptable jusqu’à ce que ce soit 90% sous charge et que le GC campe votre CPU.

Décision : Si l’utilisation du heap est constamment élevée, réduisez le nombre de shards, limitez l’usage de fielddata, corrigez les mappings (keyword vs text), ou ajoutez de la mémoire.

11) Vérifier les requêtes rejetées (saturation des pools de threads)

cr0x@server:~$ curl -s localhost:9200/_nodes/stats/thread_pool?pretty | grep -E '"rejected"|"search"|"write"' -n | head
42:          "search" : {
58:            "rejected" : 120
210:          "write" : {
226:            "rejected" : 45

Signification : Les rejets indiquent une surcharge. OpenSearch vous dit qu’il ne suit plus.

Décision : Ajoutez de la capacité, réduisez la concurrence des requêtes/indexations, ou implémentez du backpressure dans l’application. Ne faites pas « juste réessayer plus vite ».

12) Inspecter les merges OpenSearch (indicateur d’agitation disque)

cr0x@server:~$ curl -s localhost:9200/_nodes/stats/indices/merges?pretty | sed -n '1,80p'
{
  "nodes" : {
    "Q1" : {
      "indices" : {
        "merges" : {
          "current" : 7,
          "current_docs" : 180000,
          "current_size_in_bytes" : 2140000000,
          "total_throttled_time_in_millis" : 850000
        }
      }
    }
  }
}

Signification : Plusieurs merges en cours et un temps de throttling élevé suggèrent que le disque limite l’indexation et peut‑être aussi les requêtes.

Décision : Augmentez l’intervalle de refresh pendant les charges bulk, limitez l’ingestion, ou passez à un disque plus rapide. Envisagez moins de shards.

13) Valider l’analyse/tokenization (pourquoi les résultats ne correspondent pas)

cr0x@server:~$ curl -s -H 'Content-Type: application/json' localhost:9200/myindex/_analyze -d '{"text":"ACME-Invoice_2021","analyzer":"standard"}'
{"tokens":[{"token":"acme","start_offset":0,"end_offset":4,"type":"<ALPHANUM>","position":0},{"token":"invoice_2021","start_offset":5,"end_offset":17,"type":"<ALPHANUM>","position":1}]}

Signification : L’analyseur a gardé invoice_2021 comme un token. Si vous attendiez « invoice » et « 2021 » séparément, votre choix d’analyseur est incorrect.

Décision : Changez d’analyseur (ou ajoutez des sous‑champs) avant d’ajuster les requêtes. Réindexez si nécessaire.

14) Profiler une requête OpenSearch lente

cr0x@server:~$ curl -s -H 'Content-Type: application/json' localhost:9200/myindex/_search -d '{
  "profile": true,
  "query": { "match": { "body": "invoice acme" } },
  "size": 10
}' | sed -n '1,60p'
{
  "took" : 185,
  "timed_out" : false,
  "hits" : {
    "total" : {
      "value" : 12034,
      "relation" : "eq"
    }
  }
}

Signification : took: 185 ms n’est pas horrible, mais si le p95 est en secondes, inspectez les sections de profil pour voir quelle partie est coûteuse (scoring, term queries, phase fetch, etc.).

Décision : Si la phase fetch est coûteuse, réduisez les champs stockés/_source. Si le scoring est coûteux, ajustez le type de requête ou pré‑filtrez avec des mots‑clés.

15) Confirmer qu’OpenSearch écoute et ne fait pas de va‑et‑vient

cr0x@server:~$ systemctl status opensearch --no-pager
● opensearch.service - OpenSearch
     Loaded: loaded (/lib/systemd/system/opensearch.service; enabled)
     Active: active (running) since Mon 2025-12-30 11:40:11 UTC; 25min ago
       Docs: man:opensearch
   Main PID: 1920 (java)
      Tasks: 132 (limit: 4620)
     Memory: 2.7G
        CPU: 18min 12.345s

Signification : Le service est actif, mais 2.7G de mémoire sur un petit VPS peut être un signal d’alerte, pas une victoire.

Décision : Vérifiez les réglages du heap et la RAM totale. Si le processus plus le cache OS dépassent la capacité, vous êtes en route vers un OOM.

16) Vérifier les connexions MySQL et la pression sur les threads

cr0x@server:~$ mysql -e "SHOW STATUS LIKE 'Threads_connected'; SHOW STATUS LIKE 'Max_used_connections';"
+-------------------+-------+
| Variable_name     | Value |
+-------------------+-------+
| Threads_connected | 182   |
+-------------------+-------+
+----------------------+-------+
| Variable_name        | Value |
+----------------------+-------+
| Max_used_connections | 240   |
+----------------------+-------+

Signification : Un grand nombre de threads peut signifier des problèmes de pool de connexions ou une application bloquée. Cela peut aussi indiquer des requêtes lentes qui causent des accumulations.

Décision : Si les threads montent pendant les incidents, corrigez la latence des requêtes et implémentez des limites de pooling saines. Ne vous contentez pas d’augmenter max_connections.

Erreurs courantes : symptôme → cause racine → correction

1) « La recherche MySQL est lente »

Symptôme : Le point d’accès recherche fait monter le CPU, les requêtes prennent des secondes, la charge DB augmente.

Cause racine : Utiliser LIKE '%term%' sur de grandes colonnes texte, causant des scans complets ; ou trier/paginer sans index appropriés.

Correction : Utiliser la recherche par préfixe quand c’est possible ; ajouter FULLTEXT ; normaliser les champs recherchables ; ajouter des index composites pour filtres + ordre de tri ; considérer OpenSearch si vous avez besoin de tolérance aux sous‑chaînes/fautes.

2) « OpenSearch est lent de manière aléatoire »

Symptôme : Le p95 de latence monte ; des requêtes parfois à plusieurs secondes ; le CPU semble OK.

Cause racine : Pauses GC dues à une forte pression du heap, ou latence disque lors des merges de segments et des misses du cache de pages.

Correction : Réduire le nombre de shards ; corriger les mappings pour éviter les explosions de fielddata ; plafonner les agrégations ; assurer suffisamment de RAM pour le cache OS ; passer à un meilleur disque.

3) « La santé du cluster est jaune et je panique »

Symptôme : OpenSearch nœud unique affiche un statut jaune.

Cause racine : Réplicas configurés > 0 avec un seul nœud.

Correction : Mettre number_of_replicas à 0 pour ces indices et compter sur les snapshots pour la reprise.

4) « L’indexation a rendu la recherche inutilisable »

Symptôme : Pendant les imports en masse, la latence de recherche explose et des timeouts se produisent.

Cause racine : Refresh trop fréquent, merges qui dominent le disque, indexation en compétition avec la recherche sur le même nœud.

Correction : Augmenter l’intervalle de refresh pendant les imports massifs ; limiter l’ingestion ; exécuter l’indexation en masse hors‑pics ; envisager des nœuds séparés pour indexer et servir (même si cela signifie « ne pas faire ça sur un seul VPS »).

5) « OpenSearch allait bien jusqu’à ce que le disque se remplisse »

Symptôme : Échecs d’écriture, cluster en lecture seule, erreurs étranges.

Cause racine : Ne pas prendre en compte le surcoût des merges, snapshots, croissance du translog et de la rétention. Pas de plan sur les niveaux d’eau disque.

Correction : Garder un espace libre significatif ; appliquer la rétention ; monitorer le disque ; tester la taille des snapshots ; éviter les réindexations massives sans marge.

6) « Les résultats de recherche manquent des correspondances évidentes »

Symptôme : Les utilisateurs affirment que les données existent ; la recherche ne les trouve pas.

Cause racine : Mismatch analyseur/mapping (keyword vs text), surprises de tokenization, stopwords/longueur min des tokens, ou index obsolète dû à un pipeline de sync défaillant.

Correction : Vérifiez l’analyse avec _analyze ; inspectez les mappings ; implémentez un pipeline d’indexation robuste avec retries et dead‑letter ; créez des contrôles de cohérence entre MySQL et OpenSearch.

7) « On a agrandi le heap et ça a empiré »

Symptôme : Moins de GC mais pauses plus longues ; latence des requêtes pire ; lectures disque augmentées.

Cause racine : Heap trop gros qui affame le cache de pages OS ; Lucene bénéficie du cache système.

Correction : Garder le heap modéré ; laisser de la RAM pour le cache OS ; corriger les problèmes de shards/mapping plutôt que de les masquer par la taille du heap.

Checklists / plan pas à pas

Plan A : Rester avec MySQL (et être honnête sur les besoins)

  1. Définir explicitement les fonctionnalités de recherche. Mots‑clés seulement ? Préfixe ? Filtres ? Ajustement de pertinence ? Fautes de frappe ? Synonymes ? Si vous avez besoin de fautes et de synonymes, arrêtez de faire semblant.
  2. Auditer les requêtes. Remplacer les motifs %term% quand c’est possible ; s’assurer que filtres et ordres de tri ont des index.
  3. Essayer FULLTEXT quand c’est adapté. Surtout pour les cas « recherche dans titre/contenu ».
  4. Mesurer avec le slow query log. Garder un seuil stable (1–2s) et revoir les principaux coupables chaque semaine.
  5. Plan de capacité. Assurer que la DB a assez de buffer pool et de marge disque ; isoler des autres charges bruyantes.
  6. Fixer les attentes. Documenter les limites de pertinence en termes produit : « mots exacts, pas de fautes », « pas de synonymes », « pas de stemming ».

Plan B : Utiliser OpenSearch, mais ne faites pas de votre VPS un rat de laboratoire

  1. Commencez par une instance dev nœud unique. Validez les analyseurs, mappings et requêtes de base.
  2. Concevez le modèle de document. Dénormalisez. Évitez les jointures. Décidez ce qui est « text » vs « keyword ».
  3. Implémentez un pipeline d’indexation. Utilisez un pattern queue/outbox pour découpler les écritures MySQL et les mises à jour d’index, avec retries.
  4. Utilisez des alias pour une réindexation sans downtime. Versionnez les indices et swappez les alias.
  5. Définissez une stratégie de snapshots. Planifiez des snapshots et testez les restaurations.
  6. Mettez des garde‑fous. Plafonnez la complexité des requêtes, limitez la taille des agrégations et ajoutez des timeouts.
  7. Observez tout. Heap, GC, latence disque, rejets de pools de threads, distribution de latence des requêtes.
  8. Puis envisagez l’auto‑hébergement sur un petit VPS. Si vous ne pouvez pas vous engager sur snapshots, monitoring et exercices de restauration, évitez d’auto‑héberger OpenSearch sur un petit VPS.

Plan C : Si vous insistez pour OpenSearch sur un VPS, faites au moins ceci

  1. Allouez assez de RAM en laissant de la place pour le cache OS (ne pas tout donner au heap).
  2. Utilisez un stockage rapide et stable. Si le disque du VPS a des crédits de rafale, considérez que vous atteindrez le plafond.
  3. Mettre les replicas à 0 sur un nœud unique, et compter sur les snapshots.
  4. Garder le nombre de shards bas. Vous n’êtes pas un cluster ; ne jouez pas à en être un.
  5. Limiter l’indexation en masse et augmenter l’intervalle de refresh pendant les imports.
  6. Surveiller et alerter sur : disque > 80%, heap > 85%, rejets de pools de threads > 0, p95 requêtes, et événements OOM.
  7. Effectuer un exercice de restauration avant d’en avoir besoin.

FAQ

1) MySQL FULLTEXT peut‑il remplacer OpenSearch pour un petit site ?

Oui, si « petit » signifie aussi « simple ». La recherche par mots‑clés sur quelques champs avec filtres basiques est acceptable. Dès que vous avez besoin de tolérance aux fautes, de synonymes et de facettes, vous atteindrez un plafond.

2) OpenSearch est‑il surdimensionné pour un VPS ?

Souvent, oui. Pas parce qu’il ne tourne pas, mais parce qu’il ne tournera pas de façon fiable sans assez de RAM et de performances disque. Sur un petit VPS, vous êtes à une tempête de merges d’une mauvaise journée.

3) Pourquoi OpenSearch demande‑t‑il tant de mémoire ?

C’est Lucene plus une JVM plus des caches plus un overhead par shard. De plus, Lucene dépend fortement du cache de pages OS pour des lectures rapides. Si vous privez le cache OS, la recherche devient vite liée au disque.

4) Dois‑je définir le heap OpenSearch à 75% de la RAM ?

Pas sur un VPS où vous tenez à la performance. Vous avez besoin de mémoire pour le cache de pages OS. Si le heap est trop grand, vous échangez « problèmes de GC » contre « problèmes disque », et aucun n’est charmant.

5) Quel est le coût caché le plus important d’ajouter OpenSearch ?

La synchronisation et la cohérence. MySQL est la source de vérité ; OpenSearch est un index. Il vous faut un pipeline, des retries, des backfills et un moyen de détecter la dérive.

6) Puis‑je faire tourner MySQL et OpenSearch sur le même VPS ?

Vous pouvez, mais vous ne devriez probablement pas en production. La contention disque est le mode de défaillance habituel, suivi par la pression mémoire. Si vous le faites quand même, isolez les ressources et surveillez la latence disque comme si votre travail en dépendait.

7) Pourquoi la santé de mon cluster OpenSearch est‑elle jaune sur un nœud unique ?

Les replicas ne peuvent pas être alloués parce qu’il n’y a qu’un nœud. Mettez number_of_replicas à 0 pour ces indices, puis appuyez‑vous sur les snapshots pour la récupération.

8) Quand est‑il raisonnable de rester avec MySQL même si la pertinence n’est pas parfaite ?

Quand la disponibilité et la simplicité comptent plus que la sophistication de la recherche, et que vos utilisateurs tolèrent une recherche par mots exacts. Beaucoup de produits vivent tranquillement ici et s’en sortent très bien.

9) Quel est le chemin de migration le plus propre de MySQL vers OpenSearch ?

Construisez d’abord le pipeline d’indexation, backfillez dans un index versionné, validez les résultats, puis basculez les lectures progressivement (ou via un feature flag). Gardez la possibilité de revenir temporairement à la recherche MySQL.

Prochaines étapes réalisables cette semaine

Si vous hésitez encore, faites ceci dans l’ordre :

  1. Rédigez les fonctionnalités de recherche requises. Pas « agréables à avoir ». Requises.
  2. Exécutez les diagnostics. Vérifiez la latence disque, le swap et le CPU steal. Si le VPS est malade, arrêtez‑vous et réparez d’abord cela.
  3. Prototyperez en MySQL. Essayez FULLTEXT ou des schémas de préfixe structurés. Mesurez avec slow logs et EXPLAIN.
  4. Prototyperez la pertinence OpenSearch sur une machine dev. Validez les analyseurs/mappings avec _analyze. Profilez vos requêtes les plus lentes.
  5. Décidez en fonction de la réalité opérationnelle. Si vous ne pouvez pas vous engager sur snapshots, monitoring et exercices de restauration, évitez d’auto‑héberger OpenSearch sur un petit VPS.
  6. Si vous choisissez OpenSearch malgré tout : gardez un faible nombre de shards, mettez les replicas à 0 sur le nœud unique, limitez l’indexation et surveillez heap + disque comme en production — parce que c’en est.

La meilleure configuration de recherche auto‑hébergée est celle qui survive à une mauvaise journée. Vous n’avez pas besoin d’un modèle de pertinence parfait si le service est en panne. Et vous n’avez pas besoin d’un cluster magnifique si celui‑ci dévore votre VPS dès que le trafic devient réel.

← Précédent
Signets ZFS : préserver les incrémentiels quand tout se passe mal
Suivant →
Docker « OCI runtime create failed » : déchiffrez et corrigez la cause réelle

Laisser un commentaire