【问题标题】:Any reason not use PostgreSQL's built-in full text search on Heroku?有什么理由不在 Heroku 上使用 PostgreSQL 的内置全文搜索?
【发布时间】:2012-06-08 04:39:05
【问题描述】:

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

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

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

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

【问题讨论】:

    标签: postgresql heroku solr full-text-search sphinx


    【解决方案1】:

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

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

    (技术上在 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 full-text search TODO list 上完成所有工作。
    • 更好更快的词条相关性排名,在搜索时有效地自定义。
    • 常见术语或复杂查询的搜索性能可能更快。
    • 可能比 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 处理集成/同步。看起来很整洁。
    【解决方案2】:

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

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

    【讨论】:

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

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

    Full Text Search In PostgreSQL

    建立索引 LIKE 谓词的时间 -- 无
    PostgreSQL / GIN -- 40 分钟
    狮身人面像搜索 -- 6 分钟
    Apache Lucene -- 9 分钟
    倒排指数——高

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

    查询速度 LIKE 谓词 -- 90 多秒
    PostgreSQL / GIN -- 20 毫秒
    Sphinx 搜索 -- 8 毫秒
    Apache Lucene -- 80 毫秒
    倒排索引 -- 40 ms

    【讨论】:

    • 这些结果来自 2009 年。现在可能不太相关。
    【解决方案4】:

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

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

    【讨论】:

    • 刻面可以自己实现,但您可能不需要它作为 FTS 中的“功能”,我在上面的回答中举了一个例子.
    【解决方案5】:

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

    【讨论】:

      【解决方案6】:

      Postgresql 的 FTS 功能非常成熟,查找速度也相当快。值得一看。

      【讨论】:

      • 比较比说它“相当快”有用得多。
      猜你喜欢
      • 2011-04-14
      • 1970-01-01
      • 2013-04-11
      • 2023-03-25
      • 1970-01-01
      • 1970-01-01
      • 2017-07-12
      • 2019-11-02
      • 1970-01-01
      相关资源
      最近更新 更多