我正准备在 Heroku 上部署一个需要全文搜索的 Rails 应用程序。到目前为止,我一直在使用 MySQL 和 Sphinx 的 VPS 上运行它。
但是,如果我想在 Heroku 上使用 Sphinx 或 Solr,我需要付费购买附加组件。
我注意到 PostgreSQL(Heroku 上使用的数据库)具有内置的全文搜索功能。
我不能使用 Postgres 的全文搜索有什么原因吗?它比狮身人面像慢还是有其他一些主要限制?
我正准备在 Heroku 上部署一个需要全文搜索的 Rails 应用程序。到目前为止,我一直在使用 MySQL 和 Sphinx 的 VPS 上运行它。
但是,如果我想在 Heroku 上使用 Sphinx 或 Solr,我需要付费购买附加组件。
我注意到 PostgreSQL(Heroku 上使用的数据库)具有内置的全文搜索功能。
我不能使用 Postgres 的全文搜索有什么原因吗?它比狮身人面像慢还是有其他一些主要限制?
如果您对 Postgres 和 Lucene 感兴趣,为什么不两者兼而有之?查看 Postgres 的ZomboDB扩展,它将 Elasticsearch 集成为一流的索引类型。仍然是一个相当早期的项目,但对我来说它看起来很有希望。
(技术上在 Heroku 上不可用,但仍然值得一看。)
披露:我是Websolr和Bonsai Heroku 附加组件的联合创始人,所以我的观点有点偏向 Lucene。
我对 Postgres 全文搜索的了解是,它对于简单的用例来说非常可靠,但是 Lucene(以及因此 Solr 和 ElasticSearch)在性能和功能方面都优越的原因有很多。
对于初学者来说,jpountz为这个问题提供了一个真正优秀的技术答案,为什么 Solr 比 Postgres 快这么多?值得仔细阅读以真正消化。
我还评论了最近 RailsCast 的一集,比较了 Postgres 全文搜索与 Solr 的相对优缺点。让我在这里回顾一下:
LIKE
运算符。在我的脑海中,没有特别的顺序......</p>
显然,我认为基于 Lucene 的专用搜索引擎是这里更好的选择。基本上,您可以将 Lucene 视为事实上的搜索专业知识的开源存储库。
但是,如果您唯一的其他选择是LIKE
运算符,那么 Postgres 全文搜索绝对是一个胜利。
由于我刚刚将弹性搜索 (1.9) 与 postgres FTS 进行了比较,因此我认为我应该分享我的结果,因为它们比@gustavodiazjaimes 引用的更新一些。
我对 postgres 的主要担心是它没有内置 faceting,但是构建自己很简单,这是我的示例(在 django 中):
results = YourModel.objects.filter(vector_search=query)
facets = (results
.values('book')
.annotate(total=Count('book'))
.order_by('book'))
我正在使用 postgres 9.6 和 elastic-search 1.9(通过 django 上的 haystack)。下面是 elasticsearch 和 postgres 在 16 种不同类型查询中的比较。
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
为了让 postgres 达到这些多面搜索的速度,我必须在字段上使用带有 SearchVectorField 的 GIN 索引,这是 django 特有的,但我确信其他框架具有类似的向量类型。
另一个考虑因素是 pg 9.6 现在支持短语匹配,这是巨大的。
我的收获是,在大多数情况下,postgres 会更受欢迎,因为它提供:
我发现了这个惊人的比较并想分享它:
构建索引 LIKE 谓词的时间 -- 无
PostgreSQL / GIN -- 40 分钟
Sphinx 搜索 -- 6 分钟
Apache Lucene -- 9 分钟
倒排索引 -- 高
索引存储 LIKE 谓词 -- 无
PostgreSQL / GIN -- 532 MB
Sphinx 搜索 -- 533 MB
Apache Lucene -- 1071 MB
倒排索引 -- 101 MB
查询速度 LIKE 谓词 -- 90+ 秒
PostgreSQL / GIN -- 20 毫秒
Sphinx 搜索 -- 8 毫秒
Apache Lucene -- 80 毫秒
倒排索引 -- 40 毫秒
Postgres 的全文搜索在词干提取、排名/提升、同义词处理、模糊搜索等领域具有惊人的功能——但不支持分面搜索。
因此,如果 Postgres 已经在您的堆栈中并且您不需要分面,那么在寻找基于 Lucene 的解决方案之前,最好先尝试一下,以利用易于保持索引同步和保持流畅堆栈的巨大好处——至少如果全部您的应用不基于搜索。
Postgresql 的 FTS 函数在查找方面非常成熟且相当快。值得一看。