mongodb 索引去重_PostgreSQL13新特性解读Btree索引去重Deduplication
背景
PostgreSQL13.0于2020年9月24日正式release,13版本的PG帶來(lái)很多優(yōu)秀特性:比如索引的并行vacuum,增量排序,btree索引deduplication,異構(gòu)分區(qū)表邏輯訂閱等。在這里面最閃亮的特性非deduplication莫屬。
該特性由Peter Geoghegan于2020年2月27日提交,參考下面這個(gè)頁(yè)面
https://git.postgresql.org/gitweb/?p=postgresql.git;a=commit;h=0d861bbb702f8aa05c2a4e3f1650e7e8df8c8c27
下面我們來(lái)看看這個(gè)重磅特性。
Deduplication從字面意思也很好理解:“重復(fù)數(shù)據(jù)刪除”,總的來(lái)說(shuō)這個(gè)功能使得PG數(shù)據(jù)庫(kù)有了新的方式去處理重復(fù)的索引鍵值,這大大減小了btree索引所占用的空間,提升了索引掃描的性能,deduplication涉及到底層索引存儲(chǔ)結(jié)構(gòu)的變更。
在實(shí)際的生產(chǎn)環(huán)境中的數(shù)據(jù)表中可能有大量的重復(fù)數(shù)據(jù),在13版本之前,每一個(gè)重復(fù)的數(shù)據(jù)都會(huì)占用索引的一個(gè)葉子元組leaf,這些重復(fù)的key值在索引頁(yè)面中重復(fù)存儲(chǔ),帶來(lái)很大的空間浪費(fèi)。PostgreSQL13引入deduplication技術(shù),通過(guò)deduplicate_items 參數(shù)開(kāi)啟(默認(rèn)開(kāi)啟),B-Tree索引可以為重復(fù)項(xiàng)使用一種特殊的、節(jié)省空間的表示形式。
索引結(jié)構(gòu)
理解deduplication的工作原理之前我們先了解一下PG索引的結(jié)構(gòu),如下圖所示:
索引元組的結(jié)構(gòu)是Key=xxx,TID=(block=xxx,Offset=xxx),其中key代表索引的鍵值,也就是索引指向真實(shí)元組的字段值,TID是一個(gè)指向數(shù)據(jù)元組的指針數(shù)據(jù)結(jié)構(gòu),它包含兩部分,第一部分是block塊號(hào),也可以叫頁(yè)面號(hào),通過(guò)頁(yè)面號(hào)定位到數(shù)據(jù)所在頁(yè)面,第二部分是offset,代表元組在該頁(yè)面的偏移量,這個(gè)偏移量實(shí)際上就是頁(yè)面頭結(jié)構(gòu)中的linepointer的值,它是頁(yè)面內(nèi)指向真實(shí)元組的指針。
Deduplication
了解了索引結(jié)構(gòu),再來(lái)看看deduplication的原理。Deduplication的工作原理是定期將多組重復(fù)元組合并在一起,為每個(gè)組形成一個(gè)“posting list”。列鍵值key在此表示中只出現(xiàn)一次。后面是一個(gè)TID排序數(shù)組,指向表中的行。這樣我們就能理解了,deduplication就是將重復(fù)項(xiàng)的key值只存儲(chǔ)一次,然后該key對(duì)應(yīng)的TID變?yōu)橐粋€(gè)數(shù)組,這個(gè)數(shù)組分別記錄了這些相同元組的塊號(hào)和偏移量。這樣就大大減少了索引的存儲(chǔ)大小,索引掃描查詢的響應(yīng)時(shí)間也可以大大減少。
Deduplication對(duì)于CREATE INDEX和REINDEX來(lái)說(shuō)也是有益的。從表中獲取的排序輸入中遇到的每一組重復(fù)的元組在添加到當(dāng)前葉子節(jié)點(diǎn)之前被批量合并到一個(gè)“posting list”中。每個(gè)posting list元組都包含盡可能多的TID。這樣無(wú)需經(jīng)過(guò)索引的單條插入以及重復(fù)數(shù)據(jù)的合并過(guò)程。這種一次性批處理操作很適合索引的創(chuàng)建和重建,能大大加快索引的創(chuàng)建速度。
可能細(xì)心的同學(xué)可能會(huì)提出一個(gè)問(wèn)題:對(duì)于大量重復(fù)數(shù)據(jù)使用deduplication會(huì)帶來(lái)很大的收益,那么對(duì)于唯一索引會(huì)不會(huì)帶來(lái)較大的性能損耗?答案是影響很小甚至沒(méi)有影響。對(duì)于唯一索引,deduplication有特殊的處理,它通常可以直接跳到拆分葉頁(yè),從而避免在無(wú)用的deduplication過(guò)程中導(dǎo)致的性能損失。如果你還是擔(dān)心這個(gè)問(wèn)題,那么你可以選擇在唯一索引上關(guān)閉deduplicate_items這個(gè)存儲(chǔ)參數(shù),這個(gè)參數(shù)是索引級(jí)別的存儲(chǔ)參數(shù),可以對(duì)不同索引設(shè)置不同的值。
Deduplication的另一個(gè)好處在于能夠有效預(yù)防索引的膨脹,因?yàn)镻G索引并不關(guān)心mvcc機(jī)制,也就是說(shuō)一條元組經(jīng)過(guò)若干次更新后對(duì)應(yīng)的索引中也可能會(huì)插入新的行指向新版本的元組。這里為什么說(shuō)是可能,而不是一定會(huì)產(chǎn)生新的索引元組?因?yàn)镻G有HOT堆內(nèi)元組技術(shù)解決這個(gè)問(wèn)題,大體思路就是使用數(shù)據(jù)頁(yè)面上的元組結(jié)構(gòu)中的t_ctid指針指向新元組,這時(shí)就可以繼續(xù)通過(guò)原有的索引行繼續(xù)訪問(wèn)到新的元組。但是HOT技術(shù)使用場(chǎng)景是有限的,它的兩個(gè)不適用的場(chǎng)景是跨頁(yè)面以及索引的key值被修改。而在真實(shí)的生產(chǎn)環(huán)境中索引的一條元組的更改往往伴隨著key值的更改,這樣便不適用于HOT更新,索引頁(yè)就需要插入新的數(shù)據(jù),這是如果使用deduplication技術(shù)就可以將這些索引項(xiàng)合并,減小索引的大小。
另外一個(gè)有意思的話題是對(duì)于null值的處理,在我們的想象里,null值應(yīng)該不能適用deduplication,其實(shí)不然。對(duì)于大量重復(fù)的空值,B-Tree索引去重同樣有效,因?yàn)楦鶕?jù)B-Tree運(yùn)算符類的相等規(guī)則,NULL值永遠(yuǎn)不會(huì)相等。對(duì)于空值而言我們可以簡(jiǎn)單的把它理解成索引值域中的其他值。
當(dāng)然deduplication對(duì)于一些特定的數(shù)據(jù)類型不適用,這是為了保證語(yǔ)義的安全性,因?yàn)槟承?shù)據(jù)類型在一些情況下做合并是不安全的。
實(shí)驗(yàn)
下面通過(guò)實(shí)驗(yàn),來(lái)看看PG13中btree索引的變化。對(duì)比的PG版本為PG11.3和PG13.0,表test1所有列相同,表test2所有列不相同。先模擬插入數(shù)據(jù),pg11和pg13分別操作:
test=# create table test1(id int);CREATE TABLEtest=# create table test2(id int);CREATE TABLEtest1中插入16777216條重復(fù)數(shù)據(jù)
test=# select count(*) from test1; count ---------- 16777216(1 row)test2中插入16777216條不重復(fù)數(shù)據(jù)
test=# insert into test2 select generate_series(1,16777216);INSERT 0 16777216分別創(chuàng)建索引
test=# create index on test1(id);CREATE INDEXtest=# create index on test2(id);CREATE INDEX索引大小對(duì)比
PG13
test=# \di+ List of relations Schema | Name | Type | Owner | Table | Persistence | Size | Description--------+--------------+-------+----------+-------+-------------+--------+------------- public | test1_id_idx | index | postgres | test1 | permanent | 111 MB | public | test2_id_idx | index | postgres | test2 | permanent | 359 MB |(2 rows)PG11
test=# \di+ List of relations Schema | Name | Type | Owner | Table | Size | Description--------+--------------+-------+----------+-------+--------+------------- public | test1_id_idx | index | postgres | test1 | 359 MB | public | test2_id_idx | index | postgres | test2 | 359 MB |(2 rows)可以看到在數(shù)據(jù)重復(fù)的情況下,pg13的索引大小不到pg11的三分之一,沒(méi)有重復(fù)數(shù)據(jù)的情況下,兩者索引大小一致。
總結(jié)
以上是生活随笔為你收集整理的mongodb 索引去重_PostgreSQL13新特性解读Btree索引去重Deduplication的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: win7映射网络驱动器消失了_网络资源共
- 下一篇: keyshot渲染图文教程_一篇文章教你