[PROPOSAL] Effective storage of duplicates in B-tree index.
Anastasia Lubennikova <a.lubennikova@postgrespro.ru>
Hi, hackers! I'm going to begin work on effective storage of duplicate keys in B-tree index. The main idea is to implement posting lists and posting trees for B-tree index pages as it's already done for GIN. In a nutshell, effective storing of duplicates in GIN is organised as follows. Index stores single index tuple for each unique key. That index tuple points to posting list which contains pointers to heap tuples (TIDs). If too many rows having the same key, multiple pages are allocated for the TIDs and these constitute so called posting tree. You can find wonderful detailed descriptions in gin readme <https://github.com/postgres/postgres/blob/master/src/backend/access/gin/README> and articles <http://www.cybertec.at/gin-just-an-index-type/>. It also makes possible to apply compression algorithm to posting list/tree and significantly decrease index size. Read more in presentation (part 1) <http://www.pgcon.org/2014/schedule/attachments/329_PGCon2014-GIN.pdf>. Now new B-tree index tuple must be inserted for each table row that we index. It can possibly cause page split. Because of MVCC even unique index could contain duplicates. Storing duplicates in posting list/tree helps to avoid superfluous splits. So it seems to be very useful improvement. Of course it requires a lot of changes in B-tree implementation, so I need approval from community. 1. Compatibility. It's important to save compatibility with older index versions. I'm going to change BTREE_VERSION to 3. And use new (posting) features for v3, saving old implementation for v2. Any objections? 2. There are several tricks to handle non-unique keys in B-tree. More info in btree readme <https://github.com/postgres/postgres/blob/master/src/backend/access/nbtree/README> (chapter - Differences to the Lehman & Yao algorithm). In the new version they'll become useless. Am I right? 3. Microvacuum. Killed items are marked LP_DEAD and could be deleted from separate page at time of insertion. Now it's fine, because each item corresponds with separate TID. But posting list implementation requires another way. I've got two ideas: First is to mark LP_DEAD only those tuples where all TIDs are not visible. Second is to add LP_DEAD flag to each TID in posting list(tree). This way requires a bit more space, but allows to do microvacuum of posting list/tree. Which one is better? -- Anastasia Lubennikova Postgres Professional:http://www.postgrespro.com The Russian Postgres Company
Commits
-
Teach pageinspect about nbtree deduplication.
- 93ee38eade1b 13.0 landed
-
Doc: Fix deduplicate_items index term.
- e537aed61db7 13.0 landed
-
Revise BTP_HAS_GARBAGE nbtree VACUUM comments.
- 4b25f5d0ba01 13.0 cited
-
Remove unneeded "pin scan" nbtree VACUUM code.
- 9f83468b3536 13.0 landed
-
Cleanup code in reloptions.h regarding reloption handling
- 50d22de9325f 13.0 cited
-
Catch invalid typlens in a couple of places
- 8557a6f10ca6 13.0 cited
-
Compute XID horizon for page level index vacuum on primary.
- 558a9165e081 12.0 cited
-
Make heap TID a tiebreaker nbtree index column.
- dd299df8189b 12.0 cited
-
Avoid pin scan for replay of XLOG_BTREE_VACUUM in all cases
- 3e4b7d87988f 9.6.0 cited
-
Revert buggy optimization of index scans
- c7111d11b188 9.6.0 cited
-
Restructure index access method API to hide most of it at the C level.
- 65c5fcd353a8 9.6.0 cited
-
Reduce pinning and buffer content locking for btree scans.
- 2ed5b87f96d4 9.5.0 cited
-
Avoid scanning nulls at the beginning of a btree index scan.
- 1a77f8b63d15 9.2.0 cited