Heroku Postgres使用RegEx进行表演

时间:2013-06-07 18:20:34

标签: django postgresql heroku postgresql-performance

我有一个iPhone应用程序连接到在Heroku上运行的Django服务器。用户点击一个单词(如“cape”),然后向服务器查询包含该单词的任何其他段落。所以现在我用一些RegEx进行SQL查询:

  

SELECT“connectr_passage”。“id”,“connectr_passage”。“third_party_id”,   “connectr_passage”。“third_party_created”,“connectr_passage”。“source”,   “connectr_passage”。“text”,“connectr_passage”。“作者”,   “connectr_passage”。“raw_data”,“connectr_passage”。“retweet_count”,   “connectr_passage”。“favorited_count”,“connectr_passage”。“lang”,   “connectr_passage”,“位置”,   “connectr_passage”。 “author_followers_count”   “connectr_passage”。“created”,“connectr_passage”。“修改”FROM   “connectr_passage”WHERE(“connectr_passage”。“text”〜   E'(?i)\ ycape \ y'和NOT(“connectr_passage”。“text”~E'https?://'   ))

在一个包含大约412K行数据的表上,使用$ 9'dev'数据库,此查询需要1320 ms因此,对于应用程序用户来说,由于总响应时间更长,因此感觉非常慢。

在本地计算机上使用相同的数据库(MBP,8gb ram,ssd),此查询需要629.214 ms

我理解dev数据库有一些限制(不做内存缓存等),所以我的问题是:

  1. 有什么方法可以加快速度吗?在文本列上添加索引似乎没有帮助。

  2. 升级到其中一个生产数据库会显着提高性能吗?它们对我的需求来说非常昂贵。

  3. 托管连接到Heroku的数据库的其他任何好的替代方法都知道吗?

  4. 进行正则表达式sql查询以搜索术语的任何推荐替代方法?我正在考虑创建一个单词或类似的自定义索引存储,也许在某个地方有一个插件。草堆?


  5. -----编辑-----

    以下是大象对我的查询的看法:

    Sort  (cost=16979.75..16979.83 rows=34 width=175) (actual time=616.131..616.132 rows=18 loops=1)
       Sort Key: author_followers_count
       Sort Method:  quicksort  Memory: 30kB
       ->  Seq Scan on connectr_passage  (cost=0.00..16978.89 rows=34 width=175) (actual time=10.863..616.027 rows=18 loops=1)
             Filter: (((text)::text ~ '(?i)\\ycape\\y'::text) AND ((text)::text !~ 'https?://'::text))
     Total runtime: 616.229 ms
    

    所以看起来它正在进行全表扫描,因此索引无效。我是Postgres的新手,所以不确定我是否正确,但这是我的索引(通过在Django模型中设置db_index = True创建):

    public | connectr_passage_text                                | index | connectr | connectr_passage
    

    另一个编辑:

    这是最新的 - 使用了pg_trgm附加组件。

    create extension pg_trgm;
    create index passage_trgm_gin on connectr_passage using gin (text gin_trgm_ops);
    

    首次尝试:

    d2lgd5pcso4g2k=> explain analyze select * from connectr_passage where text ~ E'cape\y';
                                                          QUERY PLAN                                                       
    
     Seq Scan on connectr_passage  (cost=0.00..28627.30 rows=95 width=177) (actual time=2647.828..2647.828 rows=0 loops=1)
       Filter: ((text)::text ~ 'capey'::text)
       Rows Removed by Filter: 970514
     Total runtime: 2647.866 ms
    (4 rows)
    
    该死的,还是超级慢。但是如果我在RegEx之前做一个简单的过滤器,那就等一下:

    d2lgd5pcso4g2k=> explain analyze select * from connectr_passage where text like '%cape%' and text ~ E'(?i)\ycape\y';
                                                              QUERY PLAN                                                          
    
     Bitmap Heap Scan on connectr_passage  (cost=578.14..762.70 rows=1 width=177) (actual time=11.432..11.432 rows=0 loops=1)
       Recheck Cond: ((text)::text ~~ '%cape%'::text)
       Rows Removed by Index Recheck: 165
       Filter: ((text)::text ~ '(?i)ycapey'::text)
       Rows Removed by Filter: 468
       ->  Bitmap Index Scan on passage_trgm_gin  (cost=0.00..578.14 rows=95 width=0) (actual time=8.845..8.845 rows=633 loops=1)
             Index Cond: ((text)::text ~~ '%cape%'::text)
     Total runtime: 11.479 ms
    (8 rows)
    

    超快!

1 个答案:

答案 0 :(得分:0)

因为mu-is-short-short的建议和一些谷歌搜索,所以这几乎解决了。基本上PostgreSQL pg_trgm扩展解决了这个问题,并使查询速度提高了800倍!