我有一个简单的表foo
,其中一个列的索引,创建和填充如下:
CREATE TABLE foo
(
c1 integer,
c2 text
)
CREATE INDEX ON foo(c1);
INSERT INTO foo
SELECT i, md5(random()::text)
FROM generate_series(1, 1000000) AS i;
现在,我试图了解Index Scan
的工作原理。我 首先想到 ,btree
索引的每个叶子都包含指向 只有一页 的指针实际数据,索引列的值(用于执行Index Only Scan
)以及可能的其他内容(我不知道它是什么)。现在,我在以下查询中运行了我的实验:
EXPLAIN (ANALYZE, BUFFERS)
SELECT * FROM foo WHERE c1 < _X_;
其中_X_
从2
到255
。
查询
EXPLAIN (ANALYZE, BUFFERS)
SELECT * FROM foo WHERE c1 < 2;
返回:
Index Scan using foo_c1_idx on foo (cost=0.00..8.38 rows=1 width=37) (actual time=0.003..0.004 rows=1 loops=1)
Index Cond: (c1 < 2)
那很清楚。我们有两个随机访问(一个到索引叶,另一个到实际的数据页)和一些CPU
成本,因为我解释there。现在,通过将_X_
增加1
直至255
,0.02
我的平均成本增加了。但是当我将_X_
设置为256时,成本增加了1.02。
这是否与256
是2
的力量有关?
这里有计划:
Index Scan using foo_c1_idx on foo (cost=0.00..13.54 rows=239 width=37) (actual time=0.008..0.040 rows=254 loops=1)
Index Cond: (c1 < 255)
和
Index Scan using foo_c1_idx on foo (cost=0.00..14.56 rows=240 width=37) (actual time=0.008..0.044 rows=255 loops=1)
Index Cond: (c1 < 256)
所以,看起来我们读了一个额外的页面 顺序 来读取该行。如果是这样,我猜测叶子包含指向可以顺序读取的1页的指针。
问题: btree
索引的叶子究竟包含哪些内容?我现在认为它们包含索引列值和指向某些页面的指针(1或更多)。