【发布时间】:2022-01-16 02:44:50
【问题描述】:
我有一张表,其中包含 3 个月的约 450 万条数据。我已经对“accessedAt”列进行了索引,该列存储了纪元中的时间并具有 BIGINT 数据类型,当我运行查询时,postgres 对 700K 行进行了位图索引扫描。在(〜48.2秒)。但是当我删除索引时,它在(~4s)内对 700K 行进行了 seq 扫描。
[QUERY] explain analyze select id from access_histories where "accessedAt" >= 1631903400 and "accessedAt" <= 1633112999;
即从 2021 年 9 月 17 日至 2021 年 10 月 1 日。
Bitmap Heap Scan on access_histories (cost=14655.35..144416.85 rows=715992 width=8) (actual time=238.837..21154.597 rows=715535 loops=1)
Recheck Cond: (("accessedAt" >= 1631903400) AND ("accessedAt" <= 1633112999))
Rows Removed by Index Recheck: 1716759
Heap Blocks: exact=48015 lossy=33133
Buffers: shared hit=3 read=82972 written=8
I/O Timings: read=19860.378 write=4.389
-> Bitmap Index Scan on "access_histories_accessedAt_idx" (cost=0.00..14476.35 rows=715992 width=0) (actual time=229.267..229.272 rows=715535 loops=1)
Index Cond: (("accessedAt" >= 1631903400) AND ("accessedAt" <= 1633112999))
Buffers: shared hit=3 read=1824
I/O Timings: read=62.423
Planning:
Buffers: shared hit=20 read=1
I/O Timings: read=0.012
Planning Time: 1.168 ms
Execution Time: 21198.731 ms
删除索引后。
Seq Scan on access_histories (cost=0.00..155405.02 rows=715992 width=8) (actual time=0.035..10278.345 rows=715535 loops=1)
Filter: (("accessedAt" >= 1631903400) AND ("accessedAt" <= 1633112999))
Rows Removed by Filter: 4234466
Buffers: shared hit=23814 read=57341
I/O Timings: read=2083.283
Planning:
Buffers: shared hit=76 read=17
I/O Timings: read=7.851
Planning Time: 8.286 ms
Execution Time: 10316.716 ms
(10 rows)
所以我的问题是为什么 postgres 选择进行索引扫描,尽管顺序扫描成本更低。
p.s I know that postgres will go for seq scan if it has to query 5-10% of total data.
【问题讨论】:
-
您的查询选择了多少行(平均)?
-
试试索引
access_histories (accessedAt, id)。 -
如果您查看您的 4 个计划(预编辑和当前),我们会发现相同计划的重复执行在它们之间的时间上有很大差异。鉴于一个计划的时间安排如此不连贯,我认为尝试解释计划之间的差异没有多大意义。谁知道这种差异是否真实存在,而不仅仅是随机变化?
-
平均会因所选时间范围而异。 @The Impaler
-
@jjanes 所以我的问题是为什么 postgres 选择进行索引扫描,尽管顺序扫描成本更低。
标签: sql postgresql