PostgreSQL中COUNT(*)查询未使用索引的原因咨询
为什么这两个COUNT查询没用到索引?
这是个典型的PostgreSQL优化器成本决策问题,咱们一步步拆解背后的逻辑:
1. 带过滤条件的查询:count(*) where symbol = 'XBTUSD'
从执行计划能看到,优化器估算这个条件会返回约1640万行,而你的表总共有4500万行左右——这意味着符合条件的行占比超过35%。
对于这种高占比的过滤场景,索引扫描的优势几乎可以忽略:
- 虽然
bitmex_symbol_index比全表体积小,但遍历1640万条索引条目带来的IO和计算成本,和并行全表扫描的成本相差无几。 - 并行全表扫描能利用多个worker进程同时处理数据(你这里计划并启动了2个worker),尤其是当表数据大部分在内存缓存里时,实际执行效率反而会更高。
2. 全表COUNT查询:count(*)
统计全表行数时,优化器同样选择了并行全表扫描,原因在于:
- 遍历整个索引的成本并不比遍历全表低多少:即使索引比表小,单进程遍历索引的总耗时,可能还不如多进程并行扫描全表来得快。
- 从执行计划的实际时间来看,6秒左右完成4500万行的计数,这个速度已经是并行扫描带来的高效表现了。
什么时候索引才会被选中?
只有当过滤条件返回的行数占总表比例极低时(比如1%甚至更少),优化器才会优先选择索引扫描——因为此时只需要遍历少量索引条目就能完成计数,远快于扫描全表。
核心逻辑
PostgreSQL的查询优化器是基于成本驱动的,它会对比所有可行执行计划的预估成本,选择成本最低的那个。你的这两个查询场景中,并行全表扫描的预估成本都低于索引扫描,所以优化器自然选择了前者。
内容的提问来源于stack exchange,提问作者Yakovenko Alexey
相关产品推荐
相关产品推荐

