问题
我想知道:如何重写/更改搜索查询/策略以获得最终用户可接受的性能?
搜索
我正在为我们的用户实施搜索,为他们提供了基于以下条件在我们的系统上搜索候选人的能力:
查询
select v.id
from (
select
c.id,
c.ts_description,
c.latitude,
c.longitude,
g.group
from entities.candidates c
join entities.candidates_connections cc on cc.candidates_id = c.id
join system.groups g on cc.systems_id = g.id
) v
-- Group selection
where v.group = 'medical'
-- Location + radius
and earth_distance(ll_to_earth(v.latitude, v.longitude), ll_to_earth(50.87050439999999, -1.2191283)) < 48270
-- Full text search
and v.ts_description @@ to_tsquery('simple', 'nurse | doctor')
;
数据大小和基准
我正在处理170万条记录
我按影响顺序列出了三个条件,分别进行了基准测试:
当将它们组合在一起时,似乎要花费71s,这是3个查询的全部影响,我的期望是,当将所有3个子句放在一起时,它们将顺序工作,即对上一个子句的数据子集起作用,因此计时应该大大减少-但这没有发生。
我尝试过的事情
答案 0 :(得分:0)
似乎不需要子查询,并且使用数字字段进行过滤也是一种好习惯,因此,例如,不要使用where v.group = 'medical'
进行过滤,而是创建一个字典并使用{{1}进行过滤}
where v.group = 1
还要使用 select
DISTINCT c.id,
from entities.candidates c
join entities.candidates_connections cc on cc.candidates_id = c.id
join system.groups g on cc.systems_id = g.id
where tablename.group = 1
and earth_distance(ll_to_earth(v.latitude, v.longitude), ll_to_earth(50.87050439999999, -1.2191283)) < 48270
and v.ts_description @@ to_tsquery(0, 1 | 2)
查看并检查您的执行计划。这些快速提示将帮助您清楚地进行改进。
答案 1 :(得分:0)
我没有考虑过一些最佳实践案例,后来我实施了这些案例以显着提高性能:
tsvector索引大小减小
我在tsvector中最多存储25,000个字符,这意味着当使用更复杂的全文本搜索查询时,要做的工作量非常大,我将其减少到10,000个,这产生了很大的不同。对于我的用例,这是一个可以接受的折衷方案。
创建实例化视图
我创建了一个包含联接的实例化视图,这减轻了工作量,此外,我还在此处建立了索引,并每隔2小时运行一次并发刷新。这给了我一个非常稳定的表来使用。
即使我的搜索产生了1万条记录,但最终我还是在前端进行分页,所以我最多只能在屏幕上显示100条结果,但这使我只能加入100条记录的原始表要发回去。
增加RAM并利用pg_prewarm
我增加了服务器RAM,为我提供了足够的空间来存储实例化视图,然后在实例化视图上运行pg_prewarm。将其保存在内存中对我来说是最大的性能提升,使2m查询降低到3s。