我们的数据库中有一张表格叫做
目前,一个简单的计数查询对于那些
menus
,它有515502行。其中有一列名为status
,其类型为smallint
。目前,一个简单的计数查询对于那些
status
值为3
的文档集合需要花费700毫秒。explain analyze select count(id) from menus where status = 2;
Aggregate (cost=72973.71..72973.72 rows=1 width=4) (actual time=692.564..692.565 rows=1 loops=1)
-> Bitmap Heap Scan on menus (cost=2510.63..72638.80 rows=133962 width=4) (actual time=28.179..623.077 rows=135429 loops=1)
Recheck Cond: (status = 2)
Rows Removed by Index Recheck: 199654
-> Bitmap Index Scan on menus_status (cost=0.00..2477.14 rows=133962 width=0) (actual time=26.211..26.211 rows=135429 loops=1)
Index Cond: (status = 2)
Total runtime: 692.705 ms
(7 rows)
有一些行的列值为1,对于这些行,查询速度非常快。
explain analyze select count(id) from menus where status = 4;
QUERY PLAN
-------------------------------------------------------------------------------------------------------------------------------
Aggregate (cost=7198.73..7198.74 rows=1 width=4) (actual time=24.926..24.926 rows=1 loops=1)
-> Bitmap Heap Scan on menus (cost=40.53..7193.53 rows=2079 width=4) (actual time=1.461..23.418 rows=2220 loops=1)
Recheck Cond: (status = 4)
-> Bitmap Index Scan on menus_status (cost=0.00..40.02 rows=2079 width=0) (actual time=0.858..0.858 rows=2220 loops=1)
Index Cond: (status = 4)
Total runtime: 25.089 ms
(6 rows)
我观察到,最常用的btree索引是针对简单的基于等式查询的最佳索引策略。相比于gin和hash,btree更快。
有什么方法可以使使用索引的任何过滤器的count
查询更快吗?
我知道这是一个初学者问题,因此请提前谅解我可能犯的任何错误。
id
是主键吗?你能尝试使用count(*)
吗? - Ihor Romanchenkocount(status)
也应该可以工作。count(id)
不行的原因是 PostgreSQL 没有优化count(id)
,以证明id
是NOT NULL
,所以它认为必须获取id
字段,而这不是索引的一部分,因此无法使用索引扫描来获取。 - Craig Ringer