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
image
创建好测试表,插入测试数据。
image
下面开始分析1级结构。找到表a的索引名称
image
使用bt_metap看索引页面信息。
image
这个信息意思就是a_pkey这个索引level=0就说明只有meta page和root page,root page的id是1。
使用bt_page_stats看下索引页面的状态信息。
image
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看下索引页面内容。
image
这里面有个注意点,如果该节点是最右节点就是第一条记录就是指向页面的第一条记录,如果不是最右节点就是第二条为第一条记录,第一条记录为右节点的起始item。从bt_page_stats可以看出它的左右节点都是0号页面也就是meta page所以1号页面是最右节点,所以取第一条记录,ctid(0,1)
image

二级结构。
image
level=1代表2级结构,就是meta page,root page,leaf page。root页面id=3。
bt_page_stats信息
image
btpo_flags=2表示这是root节点,btpo=1表示不是最底层,左右节点都是0号页面。
bt_page_items信息
image
因为这个是最右节点所以是第一条记录指向下一个节点页面号。所以是(1,1)
看下1号页面的bt_page_stats信息
image
btpo_flags=1是leaf page,btpo=0是最底层。左节点页面号是0,右节点页面号是2。该节点不是最右节点。
看下1号页面bt_page_items信息
image
因为不是最右节点,所以取第二条记录(0,1)。
看下(0,1)的具体内容。
image

三级结构。
image
level=2说明有meta page,root page,一个branch page,一个leaf page,root page页面号是412。
bt_page_stats信息
image
btpo_flags=2是root节点,btpo=2不是最底层。
bt_page_items信息
image
branch节点页面号是3。

branch节点bt_page_stats。
image
btpo_flags=0,是branch节点,btpo=1不是底层节点。
branch节点bt_page_items。
image
下一叶子节点页面号是(1,1)。

leaf节点bt_page_stats。
image
btpo=0,是底层节点。btpo_flags=1是leaf page。
leaf节点bt_page_items。
image
第一条数据是(0,1)。
image

下面模拟一种异常状况进行分析。
先创建表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

正常状态时:
image
长时间运行第二个会话,关闭索引扫描出现的情况:
image
发现大部分都是heap块。看到这里知道了,这个其实是pg的hot update搞得鬼。
hot update 就是更新非索引字段时,会产生一个tuple2,索引指向ctid1,ctid1还是先指向原来的tuple1,再由tuple1指向ctid2,再由ctid2指向tuple2。如果你进行vacuum之后,就是索引指向ctid1,tuple1被回收,ctid1指向ctid2,ctid2指向tuple2。
现在用pageinspect看下这个表的索引情况:
image
这是有meta page,root page,branch page,leaf page这种结构的,root号是412。
image
image

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

目录
相关文章
|
5月前
|
存储 关系型数据库 MySQL
MySQL数据库——索引(2)-B+Tree、Hash结构,索引分类(聚集索引、二级索引)
MySQL数据库——索引(2)-B+Tree、Hash结构,索引分类(聚集索引、二级索引)
76 1
|
存储 关系型数据库 PostgreSQL
深入浅出PostgreSQL B-Tree索引结构
PostgreSQL 的B-Tree索引页分为几种类别 meta page root page # btpo_flags=2 branch page # btpo_flags=0 leaf page # btpo_flags=1 如果即
14189 0
|
存储 安全 关系型数据库
CentOS7 如何离线安装PostgreSQL数据库
如果CentOS所在的服务器限于安全原因,客户并未给我们配置访问外网的权限,那么如何安装PostgreSQL数据库呢?本文将通过具体步骤来详细讲解如何在CentOS7 系统上离线安装PostgreSQL12数据库。
3850 0
CentOS7 如何离线安装PostgreSQL数据库
|
存储 安全 索引
vacuum freeze无法回收事务号问题分析
vacuum freeze报错问题分析
4468 0
|
存储 关系型数据库 数据库
|
存储 SQL 关系型数据库
InnoDB B-TREE 索引怎么定位一条记录
本文以 WHERE 条件能够命中索引为前提,介绍查询操作定位 WHERE 条件扫描区间的第一条记录。
InnoDB B-TREE 索引怎么定位一条记录
|
存储 关系型数据库 索引
浅析InnoDB索引结构(1)
浅析InnoDB索引结构
113 0
|
存储 关系型数据库 MySQL
浅析InnoDB索引结构(2)
浅析InnoDB索引结构
|
人工智能 机器人 API
用LangChain构建大语言模型应用
LangChain 是一个开源 Python 库,任何可以编写代码的人都可以使用它来构建 LLM 支持的应用程序。 该包为许多基础模型提供了通用接口,支持提示管理,并在撰写本文时充当其他组件(如提示模板、其他 LLM、外部数据和其他工具)的中央接口。
10978 1
用LangChain构建大语言模型应用
|
SQL 存储 运维
PolarDB 大表场景性能优化技术揭秘
**背景** 很多时候业务架构设计里面最重要的一环就是数据库模型设计, 由于单机MySQL 的限制, 很多业务架构师不得不考虑对大表进行拆分, 通过中间件或者其他手段进行分库分表. 很多业务在快速发展阶段,开始考虑数据拆分的原因其实并不是计算能力遇到了瓶颈,而是海量数据的存储到达了单实例的上限,但是由于最初设计的时候没有考虑到海量数据的使用方式,或是在业务逻辑中,数据无法进行清理或归档。 运
295 0