如何加快Django用户查询查询的Postgres性能

时间:2014-05-22 16:29:20

标签: sql database postgresql indexing

随着用户数量的增加,我的Django网站开始运行缓慢。 New Relic告诉我,持续时间最长的查询是用户查询查询:

SELECT "auth_user"."id", "auth_user"."username", "auth_user"."first_name", "auth_user"."last_name", "auth_user"."email", "auth_user"."password", "auth_user"."is_staff", "auth_user"."is_active", "auth_user"."is_superuser", "auth_user"."last_login", "auth_user"."date_joined" FROM "auth_user" LEFT OUTER JOIN "account_emailaddress" ON ("auth_user"."id" = "account_emailaddress"."user_id") WHERE (UPPER("auth_user"."email"::text) = UPPER(%s) OR UPPER("account_emailaddress"."email"::text) = UPPER(%s) )

我已创建索引以希望加快上述查询:

CREATE INDEX auth_user_email_upper ON auth_user (UPPER(email));
CREATE INDEX account_emailaddress_email_upper ON account_emailaddress (UPPER(email));

不幸的是,运行与SELECT相同的EXPLAIN SELECT查询表明Postgres没有使用我刚刚创建的索引:

                                                                   QUERY PLAN
-------------------------------------------------------------------------------------------------------------------------------------------------
 Merge Left Join  (cost=0.35..17926.55 rows=2039 width=83)
   Merge Cond: (auth_user.id = account_emailaddress.user_id)
   Filter: ((upper((auth_user.email)::text) = '%s'::text) OR (upper((account_emailaddress.email)::text) = '%s'::text))
   ->  Index Scan using auth_user_pkey on auth_user  (cost=0.08..12637.91 rows=406463 width=83)
   ->  Index Scan using account_emailaddress_user_id on account_emailaddresss (cost=0.08..3868.99 rows=221167 width=26)
(5 rows)

我发现如果原始查询中没有OR条件,并且只有1 WHERE子句,则会使用索引。但是,使用这两个子句时,使用的索引支持JOIN而不是扫描。

我可以采取哪些措施来优化此查询吗?

编辑:根据要求,以下是EXPLAIN ANALYZE的输出:

EXPLAIN ANALYZE SELECT "auth_user"."id", "auth_user"."username", "auth_user"."first_name", "auth_user"."last_name", "auth_user"."email", "auth_user"."password", "auth_user"."is_staff", "auth_user"."is_active", "auth_user"."is_superuser", "auth_user"."last_login", "auth_user"."date_joined" FROM "auth_user" LEFT OUTER JOIN "account_emailaddress" ON ("auth_user"."id" = "account_emailaddress"."user_id") WHERE (UPPER("auth_user"."email"::text) = UPPER('REPLACED_EMAIL') OR UPPER("account_emailaddress"."email"::text) = UPPER('REPLACED_EMAIL') );
                                                                                QUERY PLAN
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Merge Left Join  (cost=0.26..18096.69 rows=2032 width=81) (actual time=22986.017..22986.017 rows=0 loops=1)
  Merge Cond: (http://auth_user.id = account_emailaddress.user_id)
  Filter: ((upper((auth_user.email)::text) = 'REPLACED_EMAIL'::text) OR (upper((account_emailaddress.email)::text) = 'REPLACED_EMAIL'::text))
  Rows Removed by Filter: 402817
  ->  Index Scan using auth_user_pkey on auth_user  (cost=0.08..12808.70 rows=405161 width=81) (actual time=0.017..6235.838 rows=402817 loops=1)
  ->  Index Scan using account_emailaddress_user_id on account_emailaddress  (cost=0.08..3868.99 rows=221167 width=26) (actual time=0.009..4034.638 rows=221189 loops=1)
Total runtime: 22997.255 ms
(7 rows)

编辑2:版本为:

PostgreSQL 9.3.2 on x86_64-unknown-linux-gnu, compiled by gcc (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3, 64-bit

0 个答案:

没有答案