我有一个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数据库有一些限制(不做内存缓存等),所以我的问题是:
有什么方法可以加快速度吗?在文本列上添加索引似乎没有帮助。
升级到其中一个生产数据库会显着提高性能吗?它们对我的需求来说非常昂贵。
托管连接到Heroku的数据库的其他任何好的替代方法都知道吗?
进行正则表达式sql查询以搜索术语的任何推荐替代方法?我正在考虑创建一个单词或类似的自定义索引存储,也许在某个地方有一个插件。草堆?
-----编辑-----
以下是大象对我的查询的看法:
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)
超快!
答案 0 :(得分:0)
因为mu-is-short-short的建议和一些谷歌搜索,所以这几乎解决了。基本上PostgreSQL pg_trgm扩展解决了这个问题,并使查询速度提高了800倍!