【问题标题】:Search in 300 million addresses with pg_trgm使用 pg_trgm 搜索 3 亿个地址
【发布时间】:2017-11-30 02:24:42
【问题描述】:

我的 PostgreSQL 9.3 数据库中有 3 亿个地址,我想使用 pg_trgm 来模糊搜索行。最终目的是实现一个类似于谷歌地图搜索的搜索功能。

当我使用 pg_trgm 搜索这些地址时,大约需要 30 秒才能得到结果。有很多行与默认的相似度阈值条件 0.3 匹配,但我只需要大约 5 或 10 个结果。我创建了一个三元组 GiST 索引:

CREATE INDEX addresses_trgm_index ON addresses USING gist (address gist_trgm_ops);

这是我的查询:

SELECT address, similarity(address, '981 maun st') AS sml 
FROM addresses 
WHERE address % '981 maun st' 
ORDER BY sml DESC 
LIMIT 10;

生产环境的测试表已被删除。我显示了来自我的测试环境的EXPLAIN 输出。大约有 700 万行,大约需要 1.6 秒才能得到结果。 3亿,需要30多个。

ebdb=> explain analyse select address, similarity(address, '781 maun st') as sml from addresses where address % '781 maun st' order by sml desc limit 10;
                                    QUERY PLAN                                                                            
————————————————————————————————————————————————————————————————————————————————    
 Limit  (cost=7615.83..7615.86 rows=10 width=16) (actual time=1661.004..1661.010 rows=10 loops=1)
 ->  Sort  (cost=7615.83..7634.00 rows=7268 width=16) (actual time=1661.003..1661.005 rows=10 loops=1)
     Sort Key: (similarity((address)::text, '781 maun st'::text))
     Sort Method: top-N heapsort  Memory: 25kB
     ->  Index Scan using addresses_trgm_index on addresses  (cost=0.41..7458.78 rows=7268 width=16) (actual time=0.659..1656.386 rows=5241 loops=1)
           Index Cond: ((address)::text % '781 maun st'::text)
 Total runtime: 1661.066 ms
(7 rows)

有没有提高性能的好方法或做表分区的好计划?

【问题讨论】:

  • “...我只需要大约 5 或 10 个结果”...您是否对查询设置了适当的 LIMIT?
  • 分区在 Postgres 9.3 中可用,但使用表继承实现。它在 postgres 10 中明确可用。
  • 我认为“300MM+”是指3亿?如果是这样,您应该考虑使用 ElasticSearch 或类似的东西。
  • @DavidAldridge 谢谢,我添加了限制。但是我需要按相似度排序,所以计算很慢。
  • @GaryTao 我会查看并行查询,看看那里是否有快速的胜利。 postgresql.org/docs/9.6/static/parallel-query.html

标签: postgresql pattern-matching nearest-neighbor pg-trgm bigdata


【解决方案1】:

PostgreSQL 9.3 ... 有没有提高性能的好方法或者做表分区的好计划?

表分区对根本没有帮助

是的,有一个好方法:升级到 Postgres 的当前版本。 GiST 索引有很多改进,特别是 pg_trgm 模块和一般的大数据。使用 Postgres 10 应该会更快。

您的“最近邻”搜索看起来是正确的,但对于较小的 LIMIT,请改用此等效查询:

SELECT address, similarity(address, '981 maun st') AS sml 
FROM   addresses 
WHERE  address % '981 maun st' 
ORDER  BY address &lt-> '981 maun st'
LIMIT  10;

Quoting the manual:

当只有少量的 需要最接近的匹配项。

【讨论】:

    猜你喜欢
    • 2017-02-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-06
    • 2016-03-05
    相关资源
    最近更新 更多