ChatGPT解决这个技术问题 Extra ChatGPT

有什么理由不在 Heroku 上使用 PostgreSQL 的内置全文搜索?

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

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

我注意到 PostgreSQL(Heroku 上使用的数据库)具有内置的全文搜索功能。

我不能使用 Postgres 的全文搜索有什么原因吗?它比狮身人面像慢还是有其他一些主要限制?


C
Community

编辑,2016 年 — 为什么不两者兼而有之?

如果您对 Postgres 和 Lucene 感兴趣,为什么不两者兼而有之?查看 Postgres 的 ZomboDB 扩展,它将 Elasticsearch 集成为一流的索引类型。仍然是一个相当早期的项目,但对我来说它看起来很有希望。

https://github.com/zombodb/zombodb

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

披露:我是 WebsolrBonsai Heroku 附加组件的联合创始人,所以我的观点有点偏向 Lucene。

我对 Postgres 全文搜索的了解是,它对于简单的用例来说非常可靠,但是 Lucene(以及因此 Solr 和 ElasticSearch)在性能和功能方面都优越的原因有很多。

对于初学者来说,jpountz 为这个问题提供了一个真正出色的技术答案,Why is Solr so much faster than Postgres? 值得仔细阅读以真正消化。

我还评论了 recent RailsCast episode 比较 Postgres 全文搜索与 Solr 的相对优缺点。让我在这里回顾一下:

Postgres 的实用优势

重用您已经在运行的现有服务,而不是设置和维护(或支付)其他东西。

远远优于极其缓慢的 SQL LIKE 运算符。

由于数据都在同一个数据库中,因此保持数据同步的麻烦更少——无需与某些外部数据服务 API 进行应用程序级集成。

Solr(或 ElasticSearch)的优势

在我的脑海中,没有特别的顺序......

将您的索引和搜索负载与常规数据库负载分开扩展。

更灵活的术语分析,例如重音规范化、语言词干提取、N-gram、标记删除……其他很酷的功能,如拼写检查、“丰富内容”(例如 PDF 和 Word)提取……

Solr/Lucene 可以很好地完成 Postgres 全文搜索 TODO 列表中的所有操作。

更好更快的术语相关性排名,在搜索时有效地定制。

常见术语或复杂查询的搜索性能可能更快。

可能比 Postgres 更有效的索引性能。

通过将索引与主数据存储分离,更好地容忍数据模型的变化

显然,我认为基于 Lucene 的专用搜索引擎是这里更好的选择。基本上,您可以将 Lucene 视为事实上的搜索专业知识的开源存储库。

但是,如果您唯一的选择是 LIKE 运算符,那么 Postgres 全文搜索绝对是一个胜利。


在 Postgres 9.x 中,您可以使用三元组索引加速 LIKE 搜索
谢谢,无名的马,这很有趣。看起来带有 LIKE 的 pg_trgm 是一个不合理的快速和肮脏的搜索。
Websolr 和 Bonsai 有什么区别?
在 PostgreSQL 的优势下,您忽略了迄今为止最关键的一个。您的搜索索引永远不会不同步,因为您可以使用触发器对其进行更新。与每个单独的搜索解决方案相比,这是一个巨大的优势,其中每次更新数据都需要将这些更改与独立搜索引擎同步。使用触发器,只要数据发生变化,索引同步就会完全自动进行,即使它是从您的 rails 应用程序之外的另一个代码库(Go、Node、Java、另一个 Rails 应用程序)发生变化的。 HUUUUUGE 务实取胜。
TheOldHag + aramisbear:刚刚编辑添加了关于 ZomboDB 的注释,它集成了 ES 的实用程序,同时让 Postgres 处理集成/同步。看起来很整洁。
y
yekta

由于我刚刚完成了将弹性搜索 (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 会更受欢迎,因为它提供:

更简单的堆栈没有要处理的搜索后端 api 包装器依赖项(thinking-sphinx、django-sphinx、haystack 等)。这些可能会很麻烦,因为它们可能不支持您的搜索后端所做的功能(例如干草堆分面/聚合)。具有相似的性能和功能(满足我的需要)


对于我们这些不使用 Django 的人,您能否更新您的答案以包括为获取方面而执行的实际 Postgres 查询?您是否设法在一次提取中运行您的主查询和方面查询,或者您是否必须执行单独的查询?
如果我没看错,在同等硬件上 pg 比 es 快 20 倍?
b
bendiy

我发现了这个惊人的比较并想分享它:

Full Text Search In PostgreSQL

构建索引 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 毫秒


这些结果来自 2009 年。现在可能不太相关。
D
Devi

Postgres 的全文搜索在词干提取、排名/提升、同义词处理、模糊搜索等领域具有惊人的功能——但不支持分面搜索。

因此,如果 Postgres 已经在您的堆栈中并且您不需要分面,那么在寻找基于 Lucene 的解决方案之前,最好先尝试一下,以利用轻松保持索引同步和保持流畅堆栈的巨大好处 - 至少如果全部您的应用不基于搜索。


不过,刻面可以自己实现,您可能不需要它作为 FTS 中的“功能”,我在上面的回答中通过示例解决了这个问题。
E
Eugene Lycenok

合成客户数据(1000 万条记录)的一些更新结果。

https://i.stack.imgur.com/h7iV1.png


S
Scott Marlowe

Postgresql 的 FTS 函数在查找方面非常成熟且相当快。值得一看。


比较比说它“相当快”要有用得多。

关注公众号,不定期副业成功案例分享
关注公众号

不定期副业成功案例分享

领先一步获取最新的外包任务吗?

立即订阅