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