pageinspect分析btree索引结构

pg的btree索引有4中类型的索引页面:1、meta page,每个索引都会有该页面,这个页面直接指向root page。2、root page页面,如果heap item很多,会指向新的branch page或者是leaf page。3、branch page页面指向branch page或者leaf page。4、leaf page。
我在9.4.7的版本上8kblock的int类型字段上的索引,大概一个页面可以存407条记录,也就是说,如果你是int索引且只有一个字段记录数在0-407范围内是只有root page的这是1级结构,2级结构的记录数就是407*407,3级结构就是407^3,以此类推。
现在具体开始使用pageinspect分析pg索引结构。先安装pageinspect

创建好测试表,插入测试数据。

下面开始分析1级结构。找到表a的索引名称

使用bt_metap看索引页面信息。

这个信息意思就是a_pkey这个索引level=0就说明只有meta page和root page,root page的id是1。
使用bt_page_stats看下索引页面的状态信息。

btpo_flags=2表示root节点,btpo_flags=1表示 leaf节点,btpo_flags=0表示 branch节点,btpo_flags=3表示即使root节点又是leaf节点。btpo=0是最底层,btpo_prev和btpo_next表示左右节点页面号。
使用bt_page_items看下索引页面内容。

这里面有个注意点,如果该节点是最右节点就是第一条记录就是指向页面的第一条记录,如果不是最右节点就是第二条为第一条记录,第一条记录为右节点的起始item。从bt_page_stats可以看出它的左右节点都是0号页面也就是meta page所以1号页面是最右节点,所以取第一条记录,ctid(0,1)

二级结构。

level=1代表2级结构,就是meta page,root page,leaf page。root页面id=3。
bt_page_stats信息

btpo_flags=2表示这是root节点,btpo=1表示不是最底层,左右节点都是0号页面。
bt_page_items信息

因为这个是最右节点所以是第一条记录指向下一个节点页面号。所以是(1,1)
看下1号页面的bt_page_stats信息

btpo_flags=1是leaf page,btpo=0是最底层。左节点页面号是0,右节点页面号是2。该节点不是最右节点。
看下1号页面bt_page_items信息

因为不是最右节点,所以取第二条记录(0,1)。
看下(0,1)的具体内容。

三级结构。

level=2说明有meta page,root page,一个branch page,一个leaf page,root page页面号是412。
bt_page_stats信息

btpo_flags=2是root节点,btpo=2不是最底层。
bt_page_items信息

branch节点页面号是3。

branch节点bt_page_stats。

btpo_flags=0,是branch节点,btpo=1不是底层节点。
branch节点bt_page_items。

下一叶子节点页面号是(1,1)。

leaf节点bt_page_stats。

btpo=0,是底层节点。btpo_flags=1是leaf page。
leaf节点bt_page_items。

第一条数据是(0,1)。

下面模拟一种异常状况进行分析。
先创建表create unlogged table test03 (id int primary key, info text);
vi test.sql
setrandom id 1 100
insert into test03 values(:id, repeat(md5(random()::text), 1000)) on conflict on constraint test03_pkey do update set info=excluded.info;

第一个会话开启长事务。
第二个会话运行:pgbench -M prepared -n -r -P 1 -f test.sql -c 48 -j 48 -T 2000

正常状态时:

长时间运行第二个会话,关闭索引扫描出现的情况:

发现大部分都是heap块。看到这里知道了,这个其实是pg的hot update搞得鬼。
hot update 就是更新非索引字段时,会产生一个tuple2,索引指向ctid1,ctid1还是先指向原来的tuple1,再由tuple1指向ctid2,再由ctid2指向tuple2。如果你进行vacuum之后,就是索引指向ctid1,tuple1被回收,ctid1指向ctid2,ctid2指向tuple2。
现在用pageinspect看下这个表的索引情况:

这是有meta page,root page,branch page,leaf page这种结构的,root号是412。

从这两张图可以得出(1,1)到(99,1)除了(99,1)的第一条数据都是id=1的数据。下面看下一共有多少个。

是394个。

又重新查了下发现(99,1)这个里面就没有id=1的数据。一共扫描的块数就是394+root page+leaf page=396,刚好和上面的计划中扫描块的总数相同。(这里有点小疑问,我觉得应该是计划的是对的,一共是有394条数据但是只需要扫描393个块,索引是扫描了3个,扫描了root leaf1 和leaf99,好像证明不了,按照计划来推断应该是这样算的)。

时间: 2025-01-30 15:30:33

pageinspect分析btree索引结构的相关文章

深入浅出PostgreSQL B-Tree索引结构

PostgreSQL B-Tree是一种变种(high-concurrency B-tree management algorithm),算法详情请参考src/backend/access/nbtree/README PostgreSQL 的B-Tree索引页分为几种类别 meta page root page # btpo_flags=2 branch page # btpo_flags=0 leaf page # btpo_flags=1 如果即是leaf又是root则 btpo_flags

深入分析MySQL索引结构原理、性能分析与优化详解

第一部分:基础知识: 索引 官方介绍索引是帮助MySQL高效获取数据的数据结构.笔者理解索引相当于一本书的目录,通过目录就知道要的资料在哪里,不用一页一页查阅找出需要的资料.关键字index --------------------- 唯一索引 强调唯一,就是索引值必须唯一,关键字unique index 创建索引: 1.create unique index 索引名 on 表名(列名); 2.alter table 表名 add unique index 索引名 (列名); 删除索引: 1.

mysql-为什么数据库要插入数据后再建B-Tree等结构的索引,而不是边插边建?

问题描述 为什么数据库要插入数据后再建B-Tree等结构的索引,而不是边插边建? 直接插入到B-Tree里不行吗 还有个问题,本来是直接插入到什么数据结构里的? 解决方案 voltDB好像就是往BTree里插的 解决方案二: 应该就是边插边建,除非你用的是事务或者bulkcopy 解决方案三: 索引是要排序的,只有数据插入后的排序才比较稳定,否则,索引的作用体现不出来.

[数据库]MySQL Hash索引和B-Tree索引的区别

MySQL Hash索引和B-Tree索引的区别究竟在哪里呢?相信很多人都有这样的疑问,下文对两者的区别进行了详细的分析,供您参考. MySQL Hash索引结构的特殊性,其检索效率非常高,索引的检索可以一次定位,不像B-Tree 索引需要从根节点到枝节点,最后才能访问到页节点这样多次的IO访问,所以 Hash 索引的查询效率要远高于 B-Tree 索引.  可 能很多人又有疑问了,既然 Hash 索引的效率要比 B-Tree 高很多,为什么大家不都用 Hash 索引而还要使用 B-Tree 索

InnoDB 中文参考手册 --- 11 表和索引结构

参考|参考手册|索引|中文 InnoDB 中文参考手册 --- 犬犬(心帆)翻译 11 表和索引结构MySQL 在数据库目录下的 .frm 文件中存储它的数据字典信息.但是每个 InnoDB 类型表也同样在 InnoDB 表空间内的内部的数据字典中存在它自己的进入点.当 MySQL 移除(drop) 一个表或一个数据库时,它将同时删除 .frm 文件,以及在 InnoDB 的数据字典中相对应的进入点.这就是为什么不能通过简单的删除 .frm 文件为移除数据库中的 InnoDB 类型表的原因,以及

MSSQL索引结构及其使用

一.深入浅出理解索引结构 实际上,您可以把索引理解为一种特殊的目录.微软的SQL SERVER提供了两种索引:聚集索引(clustered index,也称聚类索引.簇集索引)和非聚集索引(nonclustered index,也称非聚类索引.非簇集索引).下面,我们举例来说明一下聚集索引和非聚集索引的区别: 其实,我们的汉语字典的正文本身就是一个聚集索引.比如,我们要查"安"字,就会很自然地翻开字典的前几页,因为"安"的拼音是"an",而按照拼

MySQL的btree索引和hash索引的区别

hash 索引结构的特殊性,其检索效率非常高,索引的检索可以一次定位,不像B-Tree 索引需要从根节点到枝节点,最后才能访问到页节点这样多次的IO访问,所以 Hash 索引的查询效率要远高于 B-Tree 索引.       可能很多人又有疑问了,既然 Hash 索引的效率要比 B-Tree 高很多,为什么大家不都用 Hash 索引而还要使用 B-Tree 索引呢?任何事物都是有两面性的,Hash 索引也一样,虽然 Hash 索引效率高,但是 Hash 索引本身由于其特殊性也带来了很多限制和弊

B-Tree索引在sqlserver和mysql中的应用

在谈论数据库性能优化的时候,通常都会提到"索引",但很多人其实没有真正理解索引,并没有搞清楚索引为什么能加快检索速度,以至于在实践中并不能很好的应用索引. 事实上,索引可以说是最廉价而且十分有效一种优化手段,一般而言,设计优良的索引对查询性能优化确实能起到立竿见影的效果. 相信很多读者,都了解和使用过索引,可能也看过或者听过"新华字典"."图书馆"之类比较通俗描述,但是对索引的存储结构和本质任然还比较迷茫. 有数据结构和算法基础的读者,应该都听过

MySQL Hash索引和B-Tree索引的区别_Mysql

MySQL Hash索引结构的特殊性,其检索效率非常高,索引的检索可以一次定位,不像B-Tree 索引需要从根节点到枝节点,最后才能访问到页节点这样多次的IO访问,所以 Hash 索引的查询效率要远高于 B-Tree 索引. 可 能很多人又有疑问了,既然 Hash 索引的效率要比 B-Tree 高很多,为什么大家不都用 Hash 索引而还要使用 B-Tree 索引呢?任何事物都是有两面性的,Hash 索引也一样,虽然 Hash 索引效率高,但是 Hash 索引本身由于其特殊性也带来了很多限制和弊