应该阅读多少页才能完成 Postgres 中的简单索引查找?
How many pages should be read to fulfil a simple index seek in Postgres?
我有兴趣了解 Postgres 在使用索引时如何从 disk/cache 读取页面。
考虑查询整数的索引单列 table:
select i
into numbers
from generate_series(1, 200000) s(i);
create index idx on numbers(i);
explain (buffers, analyse)
select * from numbers where i = 456789; -- random row
这个单一索引查找需要在这个 200k 行上读取 3 页 table (Buffers: shared hit=3
):
Index Only Scan using idx on numbers (cost=0.42..8.44 rows=1 width=4) (actual time=0.010..0.010 rows=0 loops=1)
Index Cond: (i = 456789)
Heap Fetches: 0
Buffers: shared hit=3
Planning Time: 0.043 ms
Execution Time: 0.022 ms
这是预期的吗? 3页与什么有关?这仅仅是为了遍历 B 树而必须读取的索引页数吗?
背景:我正在尝试调整递归 CTE,它遍历存储在单个 table 中的链表结构作为父子关系/邻接-树。查询的递归部分是一个非常简单的索引查找,与上面类似。递归 CTE 的每个 'loop' 都会导致 3 次页面读取(如上所述),这是查询成本的主要来源。可能无法提高效率,但我想知道这是否可以以某种方式改进(目前 ~30000 页读取 10k 节点链,~25ms 缓存)。
你很幸运 autovacuum 在你 运行 你的查询之前完成,否则它会是 4 个块。
您的查询访问了中间的根节点。节点和索引的叶节点。不需要访问 table 块 (Heap Fetches: 0
),因为
所有信息都在索引中
table 的可见性地图表明 table 块是全可见的,因此没有必要参考 table 块可见性信息。
我有兴趣了解 Postgres 在使用索引时如何从 disk/cache 读取页面。
考虑查询整数的索引单列 table:
select i
into numbers
from generate_series(1, 200000) s(i);
create index idx on numbers(i);
explain (buffers, analyse)
select * from numbers where i = 456789; -- random row
这个单一索引查找需要在这个 200k 行上读取 3 页 table (Buffers: shared hit=3
):
Index Only Scan using idx on numbers (cost=0.42..8.44 rows=1 width=4) (actual time=0.010..0.010 rows=0 loops=1)
Index Cond: (i = 456789)
Heap Fetches: 0
Buffers: shared hit=3
Planning Time: 0.043 ms
Execution Time: 0.022 ms
这是预期的吗? 3页与什么有关?这仅仅是为了遍历 B 树而必须读取的索引页数吗?
背景:我正在尝试调整递归 CTE,它遍历存储在单个 table 中的链表结构作为父子关系/邻接-树。查询的递归部分是一个非常简单的索引查找,与上面类似。递归 CTE 的每个 'loop' 都会导致 3 次页面读取(如上所述),这是查询成本的主要来源。可能无法提高效率,但我想知道这是否可以以某种方式改进(目前 ~30000 页读取 10k 节点链,~25ms 缓存)。
你很幸运 autovacuum 在你 运行 你的查询之前完成,否则它会是 4 个块。
您的查询访问了中间的根节点。节点和索引的叶节点。不需要访问 table 块 (Heap Fetches: 0
),因为
所有信息都在索引中
table 的可见性地图表明 table 块是全可见的,因此没有必要参考 table 块可见性信息。