Re: [WIP] Effective storage of duplicates in B-tree index.
Peter Geoghegan <pg@heroku.com>
On Mon, Jul 4, 2016 at 2:30 AM, Heikki Linnakangas <hlinnaka@iki.fi> wrote: > I think we should pack the TIDs more tightly, like GIN does with the varbyte > encoding. It's tempting to commit this without it for now, and add the > compression later, but I'd like to avoid having to deal with multiple > binary-format upgrades, so let's figure out the final on-disk format that we > want, right from the beginning. While the idea of duplicate storage is pretty obviously compelling, there could be other, non-obvious benefits. I think that it could bring further benefits if we could use duplicate storage to change this property of nbtree (this is from the README): """ Lehman and Yao assume that the key range for a subtree S is described by Ki < v <= Ki+1 where Ki and Ki+1 are the adjacent keys in the parent page. This does not work for nonunique keys (for example, if we have enough equal keys to spread across several leaf pages, there *must* be some equal bounding keys in the first level up). Therefore we assume Ki <= v <= Ki+1 instead. A search that finds exact equality to a bounding key in an upper tree level must descend to the left of that key to ensure it finds any equal keys in the preceding page. An insertion that sees the high key of its target page is equal to the key to be inserted has a choice whether or not to move right, since the new key could go on either page. (Currently, we try to find a page where there is room for the new key without a split.) """ If we could *guarantee* that all keys in the index are unique, then we could maintain the keyspace as L&Y originally described. The practical benefits to this would be: * We wouldn't need to take the extra step described above -- finding a bounding key/separator key that's fully equal to our scankey would no longer necessitate a probably-useless descent to the left of that key. (BTW, I wonder if we could get away with not inserting a downlink into parent when a leaf page split finds an identical IndexTuple in parent, *without* changing the keyspace invariant I mention -- if we're always going to go to the left of an equal-to-scankey key in an internal page, why even have more than one?) * This would make suffix truncation of internal index tuples easier, and that's important. The traditional reason why suffix truncation is important is that it can keep the tree a lot shorter than it would otherwise be. These days, that might not seem that important, because even if you have twice the number of internal pages than strictly necessary, that still isn't that many relative to typical main memory size (and even CPU cache sizes, perhaps). The reason I think it's important these days is that not having suffix truncation makes our "separator keys" overly prescriptive about what part of the keyspace is owned by each internal page. With a pristine index (following REINDEX), this doesn't matter much. But, I think that we get much bigger problems with index bloat due to the poor fan-out that we sometimes see due to not having suffix truncation, *combined* with the page deletion algorithms restriction on deleting internal pages (it can only be done for internal pages with *no* children). Adding another level or two to the B-Tree makes it so that your workload's "sparse deletion patterns" really don't need to be that sparse in order to bloat the B-Tree badly, necessitating a REINDEX to get back to acceptable performance (VACUUM won't do it). To avoid this, we should make the internal pages represent the key space in the least restrictive way possible, by applying suffix truncation so that it's much more likely that things will *stay* balanced as churn occurs. This is probably a really bad problem with things like composite indexes over text columns, or indexes with many NULL values. -- 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