Re: [HACKERS] [WIP] Effective storage of duplicates in B-tree index.
Peter Geoghegan <pg@bowt.ie>
On Thu, Jul 11, 2019 at 8:02 AM Alexander Korotkov <a.korotkov@postgrespro.ru> wrote: > Could you please elaborate more on preserving the logical contents? I > can understand it as following: "B-Tree should have the same structure > and invariants as if each TID in posting list be a separate tuple". That's exactly what I mean. > So, if we imagine each TID to become separate tuple it would be the > same B-tree, which just can magically sometimes store more tuples in > page. Is my understanding correct? Yes. > But outside code will still > notice changes as soon as it directly accesses B-tree pages (like > contrib/amcheck does). Do you mean we need an API for accessing > logical B-tree tuples or something? Well, contrib/amcheck isn't really outside code. But amcheck's "rootdescend" option will still need to be able to supply a heap TID as just another column, and get back zero or one logical tuples from the index. This is important because retail index tuple deletion needs to be able to think about logical tuples in the same way. I also think that it might be useful for the planner to expect to get back duplicates in heap TID order in the future (or in reverse order in the case of a backwards scan). Query execution and VACUUM code outside of nbtree should be able to pretend that there is no such thing as a posting list. The main thing that the patch is missing that is needed to "preserve logical contents" is the ability to update/expand an *existing* posting list due to a retail insertion of a new duplicate that happens to be within the range of that existing posting list. This will usually be a non-HOT update that doesn't change the value for the row in the index -- that must change the posting list, even when there is available space on the page without recompressing. We must still occasionally be eager, like GIN always is, though in practice we'll almost always add to posting lists in a lazy fashion, when it looks like we might have to split the page -- the lazy approach seems to perform best. > I think in order to deduplicate "equal but distinct" values we need at > least to give up with index only scans. Because we have no > restriction that equal according to B-tree opclass values are same for > other operations and/or user output. We can either prevent index-only scans in the case of affected indexes, or prevent compression, or give the user a choice. I'm not too worried about how that will work for users just yet. > Do I understand correctly that current patch may produce posting lists > of the same value with overlapping ranges of TIDs? If so, it's > definitely wrong. Yes, it can, since the assertion fails. It looks like the assertion itself was changed to match what I expect, so I assume that this bug will be fixed in the next version of the patch. It fails with a fairly big index on text for me. > > * Maybe we could do compression with unique indexes when inserting > > values with NULLs? Note that we now treat an insertion of a tuple with > > NULLs into a unique index as if it wasn't even a unique index -- see > > the "checkingunique" optimization at the beginning of _bt_doinsert(). > > Having many NULL values in a unique index is probably fairly common. > > I think unique indexes may benefit from deduplication not only because > of NULL values. Non-HOT updates produce duplicates of non-NULL values > in unique indexes. And those duplicates can take significant space. I agree that we should definitely have an open mind about unique indexes, even with non-NULL values. If we can prevent a page split by deduplicating the contents of a unique index page, then we'll probably win. Why not try? This will need to be tested. -- Peter Geoghegan
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