在我们的数据库中,我们有一个包含515502行的表menus
。它有一个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
查询的任何提示吗?
我知道这是一个初学者级别的问题,所以请提前为我可能犯过的任何错误道歉。
答案 0 :(得分:0)
也许你的表有更多的行status = 2而不是status = 4的行,因此,第二种情况下的总表访问时间更长。 因此,对于status = 2,要考虑的行太多,因此位图堆扫描的位图将进入“有损”模式,并且在操作后需要重新检查。因此,有两件事需要考虑:要么你的结果太大(但是如果没有重组你的表,你就不能做任何事情,比如分区),或者你的' work_mem '参数是太小,不能保持间歇性的结果。如果有可能,尽量增加其价值。