brin索引是postgresql9.5版本中新增的功能,這個索引的特點就是占用空間特别小,原理是這樣的,它是将表的資料頁面按每128個資料塊(頁面)配置設定一條索引記錄,記錄這個區間的最大值和最小值,當你要查詢某條資料時,判斷這個值在哪個區間範圍内,找到呢條索引記錄,根據索引記錄掃描相應的128個資料塊。128這個值是預設的,在建立索引的時候可以進行調整的。下面用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);
下面看下要用到的pageinspect的函數
postgres=# df public.brin*
schema | name | result data type | argument data types
public
brin_metapage_info
record
page bytea, out magic text, out version integer, out pagesperrange integer, out lastrevmappage bigi
nt
normal
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
brin_page_type
text
page bytea
brin_revmap_data
setof tid
page bytea, out pages tid
brin_page_type這個是檢視索引頁面類型的,主要有三種類型meta,revmap和regular,因為這個索引隻有三個頁面是以隻看了0,1,2這三個頁面。
postgres=# select * from brin_page_type(get_raw_page('ix_a_id_brin',0));
meta
(1 row)
postgres=# select * from brin_page_type(get_raw_page('ix_a_id_brin',1));
revmap
postgres=# select * from brin_page_type(get_raw_page('ix_a_id_brin',2));
regular
postgres=# select relpages from pg_class where relname='ix_a_id_brin';
下面看下這三個頁面都是存的什麼資料。
postgres=# select * from brin_metapage_info(get_raw_page('ix_a_id_brin',0));
magic
version
pagesperrange
lastrevmappage
0xa8109cfa
1
128
這個是說這個brin索引記錄128個塊中值得範圍大小,最後一個revmap頁面是1号頁面。和之前檢視頁面類型頁面号對應。
postgres=# select * from brin_revmap_data(get_raw_page('ix_a_id_brin',1)) limit 10;
(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;
(2,101)
(2,102)
(2,103)
(2,104)
(0,0)
postgres=# select count(1) from brin_revmap_data(get_raw_page('ix_a_id_brin',1)) ;
1360
postgres=# select relpages from pg_class where relname='a';
revmap頁面能存儲1360條記錄,可以看到最後一條記錄是104,這個104是怎麼算的呢?
首先查出a表一共的頁面數13275,brin索引的每條記錄對應128個塊,13275/128=103.7,是以是104。
這個還可以看出索引條目在regluar頁面的分布情況,因為我測試的記錄條數較少,是以都在2号regluar頁面上。
postgres=# select * from brin_page_items(get_raw_page('ix_a_id_brin',2),'ix_a_id_brin') limit 10;
postgres=# select * from brin_page_items(get_raw_page('ix_a_id_brin',2),'ix_a_id_brin') offset 94 limit 10;
blknum是該索引記錄對應的起始頁面編号,第一條就是0,第二條就是128。attnum是指存放第幾個字段的意思,我隻有一個字段是以都是1,allnulls表示是不是都是空值,hasnulls表示是否存在空值。value就是記錄索引對應的128個資料塊中資料的最大值和最小值。