提高查询速度:使用LIKE进行简单的SELECT

nic*_*elo 5 django postgresql performance

我继承了一个在django 1.5 中运行的大型遗留代码库,我当前的任务是加速站点的一部分,需要大约1分钟才能加载.

我做了一个应用程序的配置文件,得到了这个:

在此输入图像描述

罪魁祸首特别是以下查询(为简洁而剥离):

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
  )
)
Run Code Online (Sandbox Code Playgroud)

基本上由一个大如查询的2场,entity_city_state_zip并且agent_city_state_zip这是character varying(200) | not null领域.

该查询被执行两次(!),同时18814.02ms每一次,和一个更多的时间更换COUNTSELECT占用额外的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
Run Code Online (Sandbox Code Playgroud)

我尝试过使用索引entity_city_state_zipagent_city_state_zip使用各种组合,例如:

CREATE INDEX ON entities_entity (upper(entity_city_state_zip));
CREATE INDEX ON entities_entity (upper(agent_city_state_zip));
Run Code Online (Sandbox Code Playgroud)

或使用varchar_pattern_ops,没有运气.

服务器正在使用这样的东西:

qs = queryset.filter(Q(entity_city_state_zip__icontains = all_city_list) |
                     Q(agent_city_state_zip__icontains = all_city_list))
Run Code Online (Sandbox Code Playgroud)

生成该查询.

我不知道还有什么可以尝试,

谢谢!

小智 1

我认为“ multiple LIKE ”和UPPER(“entities_entity ...

您可以使用:

WHERE entities_entity.entity_city_state_zip SIMILAR TO '%Atherton%|%Berkeley%'

或者是这样的:

WHERE entities_entity.entity_city_state_zip LIKE ANY(ARRAY['%Atherton%', '%Berkeley%'])


已编辑

关于 Django 中的原始 SQL 查询:

  1. https://docs.djangoproject.com/es/1.9/topics/db/sql/
  2. 如何在 django 迁移中执行原始 SQL

问候