有没有人能提出一些想法,为什么在Postgres上,下面的简单查询做向前索引扫描比向后扫描慢600倍(通常情况下是相反的):
SELECT "events".* FROM "events" ORDER BY "events"."id" ASC LIMIT 1
对比
SELECT "events".* FROM "events" ORDER BY "events"."id" DESC LIMIT 1
Id是一个主键列。两个查询都产生完全相同的计划,具有完全相同的估计值。唯一的区别是向后扫描。
另一个需要30 ms,另一个需要0.05ms的执行时间。
编辑:主键类型为bigint
EDIT:添加查询计划
-> Index Scan using events_pkey on events (cost=0.57..747008554.20 rows=200288464 width=1153) (actual time=29.662..29.6...
Planning Time: 0.090 ms
Execution Time: 29.694 ms```
—
```Limit (cost=0.57..4.30 rows=1 width=1153) (actual time=0.016..0.017 rows= 1 loops=1)
-> Index Scan Backward using events_pkey on events (cost=0.57..747008554.20 rows=200288464 width=1153) (actual time=0....
Planning Time: 0.089 ms
Execution Time: 0.049 ms
--
编辑:无论冷查询还是热查询,查询时间都保持不变。ANALYZE或VACUUM没有任何影响。
2条答案
按热度按时间g2ieeal71#
在我的头顶上,我会问:
id
列的类型是什么?我这样问是因为UUID或其他随机值将有更高的机会命中b树的不同叶子,因此在顺序遍历它们时往往会减少缓存命中。
可以使用
order by
clause创建索引。7vhp5slm2#
这个问题是通过做一个完整的真空解决的。这对我来说是新的。我不知道表的使用模式,因为我只是数据库的管理员,但我猜最近有很多修改该表?
以前的常规自动真空已经足够了。