我有一个查询从表中选择不同的值,并且我注意到初始执行后执行时间显着减少。
这是我第二次执行查询时得到的查询和相应的执行计划。
EXPLAIN ANALYZE SELECT DISTINCT integration_type FROM my_schema.my_table;
Unique (cost=0.43..576843.69 rows=7 width=2) (actual time=0.032..2826.863 rows=8 loops=1)
-> Index Only Scan using my_index on my_schema.my_table (cost=0.43..538707.38 rows=15254521 width=2) (actual time=0.031..1881.219 rows=14730886 loops=1)
Heap Fetches: 1381786
Planning Time: 0.557 ms
Execution Time: 2826.897 ms
我第一次执行查询,花了30多秒。然而,即使堆获取数量保持不变且没有变化(仍然是 1,381,786),连续执行的时间始终少于 3 秒。
我很好奇为什么尽管堆获取没有变化,但连续执行的执行时间却减少了。这是否与 PostgreSQL 采用的缓存机制或其他优化有关?
我使用的是 PostgreSQL 版本 14.9
任何关于为什么会发生这种行为以及如何进一步优化查询或数据库设置的见解或建议将不胜感激。
谢谢。
堆获取描述了仅索引扫描需要查询表以验证可见性的频率。它没有描述需要从磁盘而不是内存中获取数据的频率。当数据驻留在内存中时,您不会期望所需的堆获取次数发生变化。它仍然需要查阅这些页面,无论它们是否在内存中找到。
要确定缓冲区读取,您需要执行
EXPLAIN (ANALYZE, BUFFERS)
以下操作,然后您会得到如下行:它告诉您有多少所咨询的缓冲区已经在shared_buffers池中。
但这仍然无法告诉您缓冲区读取是否是真正的未命中(并且需要从磁盘读取),或者是在操作系统文件缓存中找到的。因此,您还应该打开 track_io_timing,这样您不仅可以获得计数,还可以获得计时。
摆脱堆获取需要 VACUUM。不存在的堆提取不需要访问磁盘。确实存在的东西可能会也可能不会被记忆所满足,这取决于你有多少记忆以及正在进行的其他活动有多少。