慢速PostgreSQL查询不使用索引

时间:2014-04-28 01:19:09

标签: django postgresql

我有一个简单的Django站点,使用PostgreSQL 9.3数据库,一个表存储用户帐户(例如姓名,电子邮件,地址,电话,活动等)。但是,我的用户模型相当大,并且有大约260万条记录。我注意到Django的管理员有点慢,所以使用django-debug-toolbar,我注意到几乎所有查询都在1毫秒内运行,除了:

SELECT COUNT(*) FROM "myapp_myuser" WHERE "myapp_myuser"."active" = true;

耗时约7000毫秒。但是,active列使用Django的标准db_index=True编制索引,生成索引:

CREATE INDEX myapp_myuser_active
  ON myapp_myuser
  USING btree
  (active);

使用EXPLAIN通过以下方式检出查询:

EXPLAIN ANALYZE VERBOSE
SELECT COUNT(*) FROM "myapp_myuser" WHERE "myapp_myuser"."active" = true;

返回:

Aggregate  (cost=109305.45..109305.46 rows=1 width=0) (actual time=7342.973..7342.974 rows=1 loops=1)
  Output: count(*)
  ->  Seq Scan on public.myapp_myuser  (cost=0.00..102638.16 rows=2666916 width=0) (actual time=0.035..4765.059 rows=2666337 loops=1)
        Output: id, created, category_id, name, email, address_1, address_2, city, active,  (...)
        Filter: myapp_myuser.active
Total runtime: 7343.031 ms

似乎根本没有使用索引。我读得对吗?

在大约500毫秒内完成仅运行SELECT COUNT(*) FROM "myapp_myuser"。为什么在运行时间存在这种差异,即使使用的唯一列是索引的?

如何更好地优化此查询?

1 个答案:

答案 0 :(得分:2)

您从宽表中选择了很多列。所以这可能没有帮助,即使它确实导致位图索引扫描。

尝试partial index

create index on myapp_myuser (active) where active = true;

我制作了一个有几百万行的测试表。

explain analyze verbose 
select count(*) from test where active = true;

"Aggregate  (cost=41800.79..41800.81 rows=1 width=0) (actual time=500.756..500.756 rows=1 loops=1)"
"  Output: count(*)"
"  ->  Bitmap Heap Scan on public.test  (cost=8085.76..39307.79 rows=997200 width=0) (actual time=126.233..386.834 rows=1000000 loops=1)"
"        Output: id, active"
"        Filter: test.active"
"        ->  Bitmap Index Scan on test_active_idx1  (cost=0.00..7836.45 rows=497204 width=0) (actual time=123.398..123.398 rows=1000000 loops=1)"
"              Index Cond: (test.active = true)"
"Total runtime: 500.794 ms"

当您编写希望使用部分索引的查询时,需要匹配表达式和WHERE子句。使用WHERE active is true在PostgreSQL中有效,但它与部分索引中的WHERE子句不匹配。这意味着您将再次进行顺序扫描。