PostgreSQL中的BRIN索引基礎(chǔ)知識和結(jié)構(gòu)是什么

這篇文章主要講解了“PostgreSQL中的BRIN索引基礎(chǔ)知識和結(jié)構(gòu)是什么”,文中的講解內(nèi)容簡單清晰,易于學(xué)習(xí)與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學(xué)習(xí)“PostgreSQL中的BRIN索引基礎(chǔ)知識和結(jié)構(gòu)是什么”吧!

成都創(chuàng)新互聯(lián)擁有一支富有激情的企業(yè)網(wǎng)站制作團(tuán)隊(duì),在互聯(lián)網(wǎng)網(wǎng)站建設(shè)行業(yè)深耕十年,專業(yè)且經(jīng)驗(yàn)豐富。十年網(wǎng)站優(yōu)化營銷經(jīng)驗(yàn),我們已為1000+中小企業(yè)提供了網(wǎng)站制作、成都做網(wǎng)站解決方案,按需策劃設(shè)計(jì),設(shè)計(jì)滿意,售后服務(wù)無憂。所有客戶皆提供一年免費(fèi)網(wǎng)站維護(hù)!

簡介
BRIN是塊范圍索引Block Range Index的簡稱,其設(shè)計(jì)思想是避免在絕對不匹配的Page中查找,而不是快速找到匹配的行,利用相對于Btree極少的空間來獲取可相對較好的查詢效率,BRIN能夠在TB級別上面的表上創(chuàng)建索引,而索引和維護(hù)開銷則很小。
BRIN在列值與其在表中的物理位置相關(guān)性較大時(shí)工作得很好,比如序列值,但在相關(guān)性不大的列值上性能較差比如隨機(jī)值上.
BRIN索引的工作原理是:首先把數(shù)據(jù)表劃分為多個(gè)范圍每個(gè)范圍有多個(gè)pages,索引存儲range的概要信息,如最大最小值等.如查詢條件包含該列,而條件值不在范圍中,那么整個(gè)范圍都會跳過,反之,需要掃描所有pages中的所有行來進(jìn)行匹配.
BRIN可以視為分區(qū)&順序掃描的加速器而不是Index.

結(jié)構(gòu)
第一(準(zhǔn)確來說是第0)頁存儲的是元數(shù)據(jù),通過元數(shù)據(jù)定位帶有摘要信息的pages.在這些頁面上的每一索引行包含每一個(gè)范圍的摘要信息.
在meta page和摘要信息之間的pages稱為反向范圍映射revmap(reverse range map),revmap實(shí)際上是指向索引行的TIDs指針數(shù)組.

對于某些范圍,revmap中的指針沒有指向索引行,這意味著仍沒有摘要信息.

索引掃描
與其他AM指向數(shù)據(jù)行不同,BRIN不會通過TID逐個(gè)返回行而是通過構(gòu)建bitmap來訪問.有兩種類型的bitmap pages,一種是精確的指向行,另外一種是不精確的執(zhí)行page,這里使用的是不精確的page.
掃描算法不復(fù)雜,順序訪問ranges map,通過指針確定包含range摘要信息的索引行,所有range的pages都會添加到bitmap中,結(jié)果bitmap的使用方法與普通的bitmap的一樣.

索引更新
在page中新增新版本行,需要確定包含該行的range并使用ranges映射找到含有摘要信息的索引行,這些操作都是簡單的算術(shù)運(yùn)算.舉個(gè)例子,range大小為4在page 13上新增一行其值為42,range的編號(從0開始)為13/4 = 3,因此在revmap中使用偏移為3的指針.
該range最小值為31,最大值為40,由于新值42超出范圍,更新最大值為42,但如果新值在范圍之內(nèi),索引不需要更新.

在索引創(chuàng)建后,所有可用范圍的摘要信息都會計(jì)算,但在表擴(kuò)展后,新pages可能會超出限制,這時(shí)候有兩種可用的方法:
1.不在馬上更新索引.在vacuum的時(shí)候才更新,或者通過函數(shù)brin_summarize_new_values更新;
2.以autosummarize選項(xiàng)創(chuàng)建索引,則馬上更新索引,該參數(shù)默認(rèn)為off.
在新范圍出現(xiàn)時(shí),revmap的大小會增長.在通過其他page增長時(shí),現(xiàn)存的行版本會移到其他pages上.

在刪除行時(shí),不需要做任何操作.最大和最小值可能已經(jīng)不存在了,但為了檢測這一點(diǎn)需要遍歷range中的所有值,這樣不太值得.索引的正確性不會影響掃描的正確性,只是對性能有所影響而已:需要掃描比實(shí)際更多的pages.PG提供了brin_desummarize_range和brin_summarize_new_values函數(shù)手工重新計(jì)算摘要信息,但如何檢測到這樣的需求?起碼傳統(tǒng)方法是做不到的.

更新行,只需要?jiǎng)h除過期版本新增一個(gè)新的即可.

使用
測試數(shù)據(jù):

testdb=# create table t_brin(id int,randomnum int);
CREATE TABLE
testdb=# 
testdb=# truncate table t_brin;
TRUNCATE TABLE
testdb=# insert into t_brin select x,random()*10000000 from generate_series(1,10000000) as x;
INSERT 0 10000000
testdb=# 
testdb=# create index idx_t_brin_id on t_brin using brin(id);
CREATE INDEX
testdb=# create index idx_t_brin_randomnum on t_brin using brin(randomnum);
CREATE INDEX
testdb=# create index idx_t_brin_btreeid on t_brin using btree(id);
CREATE INDEX
testdb=# 
testdb=# select pg_size_pretty(pg_table_size('t_brin'));
 pg_size_pretty 
----------------
 346 MB
(1 row)
testdb=# select pg_size_pretty(pg_table_size('idx_t_brin_id'));
 pg_size_pretty 
----------------
 48 kB
(1 row)
testdb=# select pg_size_pretty(pg_table_size('idx_t_brin_btreeid'));
 pg_size_pretty 
----------------
 214 MB
(1 row)

brin索引只有48KB,而Btree索引是214M,是BRIN索引大小的4565倍!

在順序列上執(zhí)行查詢:

testdb=# analyze t_brin;
ANALYZE
testdb=# explain analyze verbose select * from t_brin where id = 102345;
                                                            QUERY PLAN
-------------------------------------------------------------------------------------------------
 Index Scan using idx_t_brin_btreeid on public.t_brin  (cost=0.43..8.45 rows=1 width=8) (actual time=0.221..0.222 rows=1 loop
s=1)
   Output: id, randomnum
   Index Cond: (t_brin.id = 102345)
 Planning Time: 0.521 ms
 Execution Time: 0.266 ms
(5 rows)
testdb=# drop index idx_t_brin_btreeid;
DROP INDEX
testdb=# explain analyze verbose select * from t_brin where id = 102345;
                                                          QUERY PLAN 
-------------------------------------------------------------------------------------------------
 Bitmap Heap Scan on public.t_brin  (cost=12.03..41657.45 rows=1 width=8) (actual time=4.049..7.630 rows=1 loops=1)
   Output: id, randomnum
   Recheck Cond: (t_brin.id = 102345)
   Rows Removed by Index Recheck: 28927
   Heap Blocks: lossy=128
   ->  Bitmap Index Scan on idx_t_brin_id  (cost=0.00..12.03 rows=28902 width=0) (actual time=0.137..0.137 rows=1280 loops=1)
         Index Cond: (t_brin.id = 102345)
 Planning Time: 0.344 ms
 Execution Time: 7.666 ms
(9 rows)

等值查詢,PG選擇Btree索引,cost為8.45,執(zhí)行時(shí)間0.266 ms;
刪除Btree索引,使用BRIN索引,cost為41657.45,執(zhí)行時(shí)間為7.666 ms,是Btree的28倍.雖然慢了1個(gè)數(shù)量級,但絕對時(shí)間并不長,耗費(fèi)的空間卻少了3個(gè)數(shù)量級.

在隨機(jī)值列上執(zhí)行查詢:

testdb=# explain verbose select * from t_brin where randomnum = 102345;
                                   QUERY PLAN                                   
--------------------------------------------------------------------------------
 Gather  (cost=1000.00..97331.41 rows=2 width=8)
   Output: id, randomnum
   Workers Planned: 2
   ->  Parallel Seq Scan on public.t_brin  (cost=0.00..96331.21 rows=1 width=8)
         Output: id, randomnum
         Filter: (t_brin.randomnum = 102345)
(6 rows)
testdb=# set enable_seqscan=off;
SET
testdb=# explain verbose select * from t_brin where randomnum = 102345;
                                           QUERY PLAN                                           
------------------------------------------------------------------------------------------------
 Gather  (cost=1023.07..97354.49 rows=2 width=8)
   Output: id, randomnum
   Workers Planned: 2
   ->  Parallel Bitmap Heap Scan on public.t_brin  (cost=23.07..96354.29 rows=1 width=8)
         Output: id, randomnum
         Recheck Cond: (t_brin.randomnum = 102345)
         ->  Bitmap Index Scan on idx_t_brin_randomnum  (cost=0.00..23.07 rows=9999977 width=0)
               Index Cond: (t_brin.randomnum = 102345)
(8 rows)

PG不會使用該列上的BRIN索引而是選擇了全表掃描,禁用順序掃描后,使用brin索引,成本與全表掃描相差無幾,說明在隨機(jī)值列上的BRIN索引基本沒有效果.

testdb=# select attname, correlation from pg_stats where tablename='t_brin' order by correlation desc nulls last;
  attname  | correlation  
-----------+--------------
 id        |            1
 randomnum | 0.0016428155
(2 rows)

查詢統(tǒng)計(jì)信息,id列相關(guān)性是1,而隨機(jī)值列相關(guān)性是0.0016428155,相差巨大.

感謝各位的閱讀,以上就是“PostgreSQL中的BRIN索引基礎(chǔ)知識和結(jié)構(gòu)是什么”的內(nèi)容了,經(jīng)過本文的學(xué)習(xí)后,相信大家對PostgreSQL中的BRIN索引基礎(chǔ)知識和結(jié)構(gòu)是什么這一問題有了更深刻的體會,具體使用情況還需要大家實(shí)踐驗(yàn)證。這里是創(chuàng)新互聯(lián),小編將為大家推送更多相關(guān)知識點(diǎn)的文章,歡迎關(guān)注!

本文題目:PostgreSQL中的BRIN索引基礎(chǔ)知識和結(jié)構(gòu)是什么
網(wǎng)頁網(wǎng)址:http://bm7419.com/article14/geisge.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站維護(hù)、標(biāo)簽優(yōu)化、Google、電子商務(wù)網(wǎng)站制作、網(wǎng)站建設(shè)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)

搜索引擎優(yōu)化