pageinsepect分析brin索引

brin索引是postgresql9.5版本中新增的功能,这个索引的特点就是占用空间特别小,原理是这样的,它是将表的数据页面按每128个数据块(页面)分配一条索引记录,记录这个区间的最大值和最小值,当你要查询某条数据时,判断这个值在哪个区间范围内,找到呢条索引记录,根据索引记录扫描相应的128个数据块。128这个值是默认的,在创建索引的时候可以进行调整的。下面用pageinspect这个插件对brin索引进行下简单的分析。

创建测试表,安装pageinspect,创建brin索引。

postgres=# create extension pageinspect;
CREATE EXTENSION
postgres=# create table a(id int);
CREATE TABLE
postgres=# insert into a select generate_series(1,3000000);
INSERT 0 3000000
postgres=# create index ix_a_id_brin on a using brin(id) with (pages_per_range=128);

CREATE INDEX

下面看下要用到的pageinspect的函数


postgres=# df public.brin*

                                                                                                           List of functions

Schema | Name | Result data type | Argument data types

                                                                             |  Type  
public brin_metapage_info record page bytea, OUT magic text, OUT version integer, OUT pagesperrange integer, OUT lastrevmappage bigi
nt normal
public brin_page_items SETOF record page bytea, index_oid regclass, OUT itemoffset integer, OUT blknum integer, OUT attnum integer, OUT
allnulls boolean, OUT hasnulls boolean, OUT placeholder boolean, OUT value text normal
public brin_page_type text page bytea
normal
public brin_revmap_data SETOF tid page bytea, OUT pages tid

(4 rows)

brin_page_type这个是查看索引页面类型的,主要有三种类型meta,revmap和regular,因为这个索引只有三个页面所以只看了0,1,2这三个页面。


postgres=# select * from brin_page_type(get_raw_page('ix_a_id_brin',0));

brin_page_type

meta
(1 row)

postgres=# select * from brin_page_type(get_raw_page('ix_a_id_brin',1));

brin_page_type

revmap
(1 row)

postgres=# select * from brin_page_type(get_raw_page('ix_a_id_brin',2));

brin_page_type

regular
(1 row)
postgres=# select relpages from pg_class where relname='ix_a_id_brin';

relpages

    3

(1 row)

下面看下这三个页面都是存的什么数据。

meta页面

postgres=# select * from brin_metapage_info(get_raw_page('ix_a_id_brin',0));

magic version pagesperrange lastrevmappage
0xA8109CFA 1 128 1

这个是说这个brin索引记录128个块中值得范围大小,最后一个revmap页面是1号页面。和之前查看页面类型页面号对应。

revmap页面

postgres=# select * from brin_revmap_data(get_raw_page('ix_a_id_brin',1)) limit 10;

pages

(2,1)
(2,2)
(2,3)
(2,4)
(2,5)
(2,6)
(2,7)
(2,8)
(2,9)
(2,10)
(10 rows)
postgres=# select * from brin_revmap_data(get_raw_page('ix_a_id_brin',1)) offset 100 limit 10;

pages

(2,101)
(2,102)
(2,103)
(2,104)
(0,0)
(0,0)
(0,0)
(0,0)
(0,0)
(0,0)
(10 rows)
postgres=# select count(1) from brin_revmap_data(get_raw_page('ix_a_id_brin',1)) ;

count

1360
(1 row)
postgres=# select relpages from pg_class where relname='a';

relpages

13275

(1 row)

revmap页面能存储1360条记录,可以看到最后一条记录是104,这个104是怎么算的呢?
首先查出a表一共的页面数13275,brin索引的每条记录对应128个块,13275/128=103.7,所以是104。
这个还可以看出索引条目在regluar页面的分布情况,因为我测试的记录条数较少,所以都在2号regluar页面上。

regluar页面

postgres=# select * from brin_page_items(get_raw_page('ix_a_id_brin',2),'ix_a_id_brin') limit 10;

(10 rows)
postgres=# select * from brin_page_items(get_raw_page('ix_a_id_brin',2),'ix_a_id_brin') offset 94 limit 10;

(10 rows)

blknum是该索引记录对应的起始页面编号,第一条就是0,第二条就是128。attnum是指存放第几个字段的意思,我只有一个字段所以都是1,allnulls表示是不是都是空值,hasnulls表示是否存在空值。value就是记录索引对应的128个数据块中数据的最大值和最小值。

上一篇:pg_upgrade大版本升级


下一篇:阿里云域名注册与备案、服务器ECS购买与登录使用