任何理由不使用PostgreSQL内置的全文searchHeroku?

我准备在Heroku上部署一个需要全文search的Rails应用程序。 到目前为止,我已经使用MySQL和Sphinx在VPS上运行它。

但是,如果我想在Heroku上使用Sphinx或Solr,那么我需要为附加组件付费。

我注意到PostgreSQL(在Heroku上使用的数据库)有内置的全文searchfunction。

有没有一个原因,我不能使用Postgres的全文search? 它比狮身人面像慢还是有一些其他的主要限制?

编辑,2016 – 为什么不是两个?

如果你对Postgres和Lucene感兴趣,为什么不呢? 查看Postgres的ZomboDB扩展,它将Elasticsearch集成为一stream的索引types。 还是一个相当早期的项目,但它看起来真的很有希望给我。

(技术上在Heroku上不可用,但仍值得一看。)


披露:我是Websolr和盆景 Heroku附加组件的创始人之一,所以我的观点有点偏向于Lucene。

我对Postgres全文search的看法是它对于简单的用例非常稳固,但是为什么Lucene(以及Solr和ElasticSearch)在性能和function方面都是优越的呢。

对于初学者来说, jpountz提供了一个真正优秀的技术答案, 为什么Solr比Postgres快得多? 这是值得一读通过真正消化。

我还评论了最近RailsCast的一集,比较了Postgres全文search与Solr的相对优缺点。 让我回顾一下:

对Postgres的语用优势

  • 重用已经运行的现有服务,而不是设置和维护(或支付)其他服务。
  • 远远优于非常慢的SQL LIKE运算符。
  • 保持数据同步的麻烦较less,因为它们都在同一个数据库中 – 没有与某些外部数据服务API的应用程序级集成。

Solr(或ElasticSearch)的优点

在我头顶,没有特别的顺序

  • 将您的索引和search负载分别与常规数据库负载分开放大。
  • 其他很酷的function,如拼写检查,“丰富的内容”(如PDF和Word),提取…
  • Solr / Lucene可以在Postgres全文searchTODO列表上完成所有工作。
  • 更好和更快的术语相关性排名,在search时有效地定制。
  • 常见术语或复杂查询的search性能可能会更快。
  • 可能比Postgres更有效的索引性能。
  • 通过将索引与主数据存储区分离,更好地容忍数据模型中的更改

显然,我认为基于Lucene的专用search引擎是更好的select。 基本上,您可以将Lucene视为事实上的search专家的开源资源库。

但是如果你唯一的select是LIKE运算符,那么Postgres全文search是一个明确的胜利。

我发现这个惊人的比较,并希望分享它:

PostgreSQL中的全文search

编译索引的时间LIKE谓词 – 无
PostgreSQL / GIN – 40分钟
狮身人面像search – 6分钟
Apache Lucene – 9分钟
倒挂指数 – 高

索引存储LIKE谓词 – 无
PostgreSQL / GIN – 532 MB
狮身人面像search – 533 MB
Apache Lucene – 1071 MB
倒置索引 – 101 MB

查询速度LIKE谓词 – 90+秒
PostgreSQL / GIN – 20毫秒
狮身人面像search – 8毫秒
Apache Lucene – 80毫秒
倒置索引 – 40毫秒

由于我刚刚通过比较弹性search(1.9)和Postgres FTS的努力,我想我应该分享我的结果,因为它们比@gustavodiazjaimes的更多。

我对postgres的主要关注是它没有内置的构面,但这是微不足道的build立自己,这是我的例子(在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上的干草堆)。 这里是elasticsearch和postgres在16种不同types的查询之间的比较。

  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达到这些速度的分面search,我不得不使用一个SearchVectorField字段上的GIN索引,这是Django特定的,但我相信其他框架有一个相似的向量types。

另一个考虑是pg 9.6现在支持短语匹配,这是巨大的。

我拿走的是,大多数情况下postgres将是可取的,因为它提供了:

  1. 更简单的堆栈
  2. 没有search后端api封装依赖来抗衡(思维狮身人面像,Django狮身人面像,干草堆等)。 这可能是一个拖动,因为他们可能不支持你的search后端function(例如干草堆面/聚合)。
  3. 有类似的性能和function(为我的需要)

Postgres的全文search在阻塞,排名/提升,同义词处理,模糊search等方面具有惊人的function – 但是不支持分面search。

所以,如果Postgres已经在你的堆栈中,并且你不需要面对,那么最好在试图使用Lucene基础的解决scheme之前,让它们保持索引同步和保持圆滑的堆栈的巨大好处 – 至less如果所有的你的应用程序不是基于search。

PostgreSQL的FTSfunction在查找时已经成熟,速度相当快。 值得一看。