Je me prépare à déployer une application Rails sur Heroku qui nécessite une recherche en texte intégral. Jusqu'à présent, je l'ai utilisé sur un serveur VPS utilisant MySQL avec Sphinx.
Cependant, si je veux utiliser Sphinx ou Solr sur Heroku, je devrai payer pour un add-on.
Je remarque que PostgreSQL (la base de données utilisée sur Heroku) possède une fonctionnalité intégrée de recherche en texte intégral.
Y a-t-il une raison pour laquelle je ne pourrais pas utiliser la recherche en texte intégral de Postgres? Est-ce plus lent que Sphinx ou existe-t-il une autre limitation majeure?
Si vous êtes intéressé par Postgres vs. Lucene, pourquoi pas les deux? Découvrez l'extension ZomboDB pour Postgres, qui intègre Elasticsearch en tant que type d'index de première classe. Encore un projet assez précoce, mais il me semble vraiment prometteur.
(Techniquement non disponible sur Heroku, mais qui mérite d'être regardé.)
Divulgation: Je suis cofondatrice des add-ons Websolr et Bonsai Heroku, mon point de vue est donc un peu biaisé en faveur de Lucene.
D'après ce que j'ai lu sur la recherche en texte intégral dans Postgres, elle est assez solide pour les cas d'utilisation simples, mais il existe plusieurs raisons pour lesquelles Lucene (et donc Solr et ElasticSearch) est supérieure tant en termes de performances que de fonctionnalités.
Pour commencer, jpountz fournit une réponse technique vraiment excellente à la question, Pourquoi Solr est-il tellement plus rapide que Postgres? Cela vaut la peine de lire deux ou trois lectures pour bien digérer.
J'ai également commenté un récent épisode de RailsCast comparant les avantages et les inconvénients relatifs de la recherche en texte intégral de Postgres par rapport à Solr. Permettez-moi de récapituler ici:
LIKE
, extrêmement lent.De mémoire, sans ordre particulier…
Clairement, je pense qu'un moteur de recherche dédié basé sur Lucene est la meilleure option ici. En gros, vous pouvez penser à Lucene en tant que référentiel open source de compétences en matière de recherche.
Mais si votre seule autre option est l'opérateur LIKE
, la recherche en texte intégral de Postgres constitue un avantage certain.
Comme je viens de comparer la recherche élastique (1,9) à la post-FTS FTS, je me suis dit que je devrais partager mes résultats, car ils sont un peu plus récents que ceux mentionnés par @gustavodiazjaimes.
Mon souci principal avec postgres était de ne pas avoir de facettes intégrées, mais c'est simple à construire soi-même, voici mon exemple (sous Django):
results = YourModel.objects.filter(vector_search=query)
facets = (results
.values('book')
.annotate(total=Count('book'))
.order_by('book'))
J'utilise postgres 9.6 et elastic-search 1.9 (avec haystack sur Django). Voici une comparaison entre elasticsearch et postgres à travers 16 types de requêtes.
es_times pg_times es_times_faceted pg_times_faceted
0 0.065972 0.000543 0.015538 0.037876
1 0.000292 0.000233 0.005865 0.007130
2 0.000257 0.000229 0.005203 0.002168
3 0.000247 0.000161 0.003052 0.001299
4 0.000276 0.000150 0.002647 0.001167
5 0.000245 0.000151 0.005098 0.001512
6 0.000251 0.000155 0.005317 0.002550
7 0.000331 0.000163 0.005635 0.002202
8 0.000268 0.000168 0.006469 0.002408
9 0.000290 0.000236 0.006167 0.002398
10 0.000364 0.000224 0.005755 0.001846
11 0.000264 0.000182 0.005153 0.001667
12 0.000287 0.000153 0.010218 0.001769
13 0.000264 0.000231 0.005309 0.001586
14 0.000257 0.000195 0.004813 0.001562
15 0.000248 0.000174 0.032146 0.002246
count mean std min 25% 50% 75% max
es_times 16.0 0.004382 0.016424 0.000245 0.000255 0.000266 0.000291 0.065972
pg_times 16.0 0.000209 0.000095 0.000150 0.000160 0.000178 0.000229 0.000543
es_times_faceted 16.0 0.007774 0.007150 0.002647 0.005139 0.005476 0.006242 0.032146
pg_times_faceted 16.0 0.004462 0.009015 0.001167 0.001580 0.002007 0.002400 0.037876
Afin d'obtenir ces vitesses pour les recherches à facettes, je devais utiliser un index GIN sur le champ avec SearchVectorField, qui est spécifique à Django, mais je suis sûr que d'autres frameworks ont un type de vecteur similaire.
Une autre considération est que la page 9.6 supporte maintenant la correspondance de phrase, ce qui est énorme.
Mon argument est que postgres est dans la plupart des cas préférable car il offre:
J'ai trouvé cette comparaison étonnante et je veux la partager:
Recherche en texte intégral dans PostgreSQL
Temps nécessaire pour construire le prédicat Index LIKE - aucun
PostgreSQL/GIN - 40 min
Recherche Sphinx - 6 min
Apache Lucene - 9 min
Index inversé - élevé
Index Storage LIKE prédicat - aucun
PostgreSQL/GIN - 532 Mo
Sphinx Search - 533 MB
Apache Lucene - 1071 MB
Index inversé - 101 Mo
Requête vitesse LIKE - 90 secondes et plus
PostgreSQL/GIN - 20 ms
Recherche de sphinx - 8 ms
Apache Lucene - 80 ms
Index inversé - 40 ms
La recherche en texte intégral de Postgres offre des capacités étonnantes dans les domaines de la radicalisation, du classement/renforcement, de la gestion des synonymes, de la recherche floue, entre autres - mais ne prend pas en charge la recherche par facettes.
Donc, si Postgres est déjà dans votre pile et que vous n'avez pas besoin de facettes, essayez-le pour profiter de l'énorme avantage de pouvoir synchroniser facilement les index et de maintenir une pile élégante, avant de rechercher des solutions basées sur Lucene - du moins si tout votre application n'est pas basée sur la recherche.
La fonction FTS de Postgresql est mature et assez rapide lors des recherches. Ça vaut le coup d'oeil à coup sûr.