我已经继承了一个大的遗留代码库,它在django 1.5中运行,我目前的任务是加速一个网站部分,需要加载〜1min。提高查询速度:简单选择与喜欢
我做了应用程序的轮廓,并得到这个:
特别罪魁祸首是以下查询(剥离为了简洁):
SELECT COUNT(*) FROM "entities_entity" WHERE (
"entities_entity"."date_filed" <= '2016-01-21' AND (
UPPER("entities_entity"."entity_city_state_zip"::text) LIKE UPPER('%Atherton%') OR
UPPER("entities_entity"."entity_city_state_zip"::text) LIKE UPPER('%Berkeley%') OR
-- 34 more of these
UPPER("entities_entity"."agent_city_state_zip"::text) LIKE UPPER('%Atherton%') OR
UPPER("entities_entity"."agent_city_state_zip"::text) LIKE UPPER('%Berkeley%') OR
-- 34 more of these
)
)
基本上由上大查询两个字段,entity_city_state_zip
和agent_city_state_zip
这是character varying(200) | not null
字段。
查询是执行两次(!),同时每次18814.02ms,和一次更换COUNT
的SELECT
占用额外20216.49
(我要去缓存COUNT
结果)
的这样的解释看起来:
Aggregate (cost=175867.33..175867.34 rows=1 width=0) (actual time=17841.502..17841.502 rows=1 loops=1)
-> Seq Scan on entities_entity (cost=0.00..175858.95 rows=3351 width=0) (actual time=0.849..17818.551 rows=145075 loops=1)
Filter: ((date_filed <= '2016-01-21'::date) AND ((upper((entity_city_state_zip)::text) ~~ '%ATHERTON%'::text) OR (upper((entity_city_state_zip)::text) ~~ '%BERKELEY%'::text) (..skipped..) OR (upper((agent_city_state_zip)::text) ~~ '%ATHERTON%'::text) OR (upper((agent_city_state_zip)::text) ~~ '%BERKELEY%'::text) OR (upper((agent_city_state_zip)::text) ~~ '%BURLINGAME%'::text)))
Rows Removed by Filter: 310249
Planning time: 2.110 ms
Execution time: 17841.944 ms
我对entity_city_state_zip
和agent_city_state_zip
使用各种字体,使用索引尝试s组合如:
CREATE INDEX ON entities_entity (upper(entity_city_state_zip));
CREATE INDEX ON entities_entity (upper(agent_city_state_zip));
或使用varchar_pattern_ops
,没有运气。
服务器使用这样的事情:
qs = queryset.filter(Q(entity_city_state_zip__icontains = all_city_list) |
Q(agent_city_state_zip__icontains = all_city_list))
生成查询。
我不知道还有什么可以尝试的,
谢谢!
'LIKE'查询,这与'开始 '%...''将不使用任何B树索引(包括'xxx_pattern_ops')。只有在模式匹配时才会选择这些索引。 (f.ex.' col LIKE'XXX%''或'col〜'^ XXX'')。你可以试试['pg_trgm'模块](http://www.postgresql.org/docs/current/static/pgtrgm.html),[它为你提供了一个合适的索引](http://dba.stackexchange。 COM /问题/ 10694 /模式匹配与样类似到或正则表达式合的PostgreSQL/10696)。 (你可以使用'ilike'来代替like'''lower()'/'upper()'调用)。 – pozs
@pozs我不知道!我会试一试 – NicoSantangelo
我至少想知道'Seq Scan'有什么影响,以及索引扫描是否可以被替代。看看'set enable_seqscan = false'对计划有什么影响。数据库是否从SSD运行? –