我有一个简单的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"
。为什么在运行时间存在这种差异,即使使用的唯一列是索引的?
如何更好地优化此查询?
答案 0 :(得分:2)
您从宽表中选择了很多列。所以这可能没有帮助,即使它确实导致位图索引扫描。
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子句不匹配。这意味着您将再次进行顺序扫描。