Re: WIP: BRIN multi-range indexes
John Naylor <john.naylor@2ndquadrant.com>
From: John Naylor <john.naylor@2ndquadrant.com>
To: Tomas Vondra <tomas.vondra@2ndquadrant.com>
Cc: Alvaro Herrera <alvherre@2ndquadrant.com>,
pgsql-hackers <pgsql-hackers@postgresql.org>
Date: 2020-09-18T21:06:49Z
Lists: pgsql-hackers
On Fri, Sep 18, 2020 at 7:40 AM Tomas Vondra <tomas.vondra@2ndquadrant.com> wrote: > > On Thu, Sep 17, 2020 at 06:48:11PM -0400, John Naylor wrote: > >I wrote: > > > >> Hmm, I came across that paper while doing background reading. Okay, > >> now I get that "% (filter->nbits - 1)" is the second hash function in > >> that scheme. But now I wonder if that second function should actually > >> act on the passed "value" (the original hash), so that they are > >> actually independent, as required. In the language of that paper, the > >> patch seems to have > >> > >> g(x) = h1(x) + i*h2(h1(x)) + f(i) > >> > >> instead of > >> > >> g(x) = h1(x) + i*h2(x) + f(i) > >> > >> Concretely, I'm wondering if it should be: > >> > >> big_h = DatumGetUint32(hash_uint32(value)); > >> h = big_h % filter->nbits; > >> -d = big_h % (filter->nbits - 1); > >> +d = value % (filter->nbits - 1); > >> > >> But I could be wrong. > > > >I'm wrong -- if we use different operands to the moduli, we throw away > >the assumption of co-primeness. But I'm still left wondering why we > >have to re-hash the hash for this to work. In any case, there should > >be some more documentation around the core algorithm, so that future > >readers are not left scratching their heads. > > > > Hmm, good question. I think we don't really need to hash it twice. It > does not rally achieve anything - it won't reduce number of collisions > or anything like that. Yeah, looking back at the discussion you linked previously, I think it's a holdover from when the uint32 was rehashed with k different seeds. Anyway, after thinking about it some more, I still have doubts about the mapping algorithm. There are two stages to a hash mapping -- hashing and modulus. I don't think a single hash function (whether rehashed or not) can be turned into two independent functions via a choice of second modulus. At least, that's not what the Kirsch & Mitzenmacher paper is claiming. Since we're not actually applying two independent hash functions on the scan key, we're kind of shooting in the dark. It turns out there is something called a one-hash bloom filter, and the paper in [1] has a straightforward algorithm. Since we can implement it exactly as stated in the paper, that gives me more confidence in the real-world false positive rate. It goes like this: Partition the filter bitmap into k partitions of similar but unequal length, corresponding to consecutive prime numbers. Use the primes for moduli of the uint32 value and map it to the bit of the corresponding partition. For a simple example, let's use 7, 11, 13 for partitions in a filter of size 31. The three bits are: value % 7 7 + (value % 11) 7 + 11 + (value % 13) We could store a const array of the first 256 primes. The largest such prime is 1613, so with k=7 we can support up to ~11k bits, which is more than we'd like to store anyway. Then we store the array index of the largest prime in the 8bits of padding we currently have in BloomFilter struct. One wrinkle is that the sum of k primes is not going to match m exactly. If the sum is too small, we can trim a few bits off of the filter bitmap. If the sum is too large, the last partition can spill into the front of the first one. This shouldn't matter much in the common case since we need to round m to the nearest byte anyway. This should be pretty straightforward to turn into code and I can take a stab at it. Thoughts? [1] https://www.researchgate.net/publication/284283336_One-Hashing_Bloom_Filter -- John Naylor https://www.2ndQuadrant.com/ PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services
Commits
-
BRIN minmax-multi indexes
- ab596105b55f 14.0 landed
-
BRIN bloom indexes
- 77b88cd1bb90 14.0 landed
-
Support the old signature of BRIN consistent function
- a681e3c107aa 14.0 landed
-
Remove unnecessary pg_amproc BRIN minmax entries
- a68dfa27d42f 14.0 landed
-
Optimize allocations in bringetbitmap
- 8e4b332e88b8 14.0 landed
-
Move IS [NOT] NULL handling from BRIN support functions
- 72ccf55cb99c 14.0 landed
-
Pass all scan keys to BRIN consistent function at once
- a1c649d889bd 14.0 landed
-
Properly detoast data in brin_form_tuple
- d2d3a4bd33d2 9.5.24 landed
- bae31e75f777 9.6.20 landed
- 0b96fc977c5b 10.15 landed
- 895d0f0e8218 11.10 landed
- 8149e9f9a0d6 12.5 landed
- 6a7b55f3716f 13.1 landed
- 7577dd84807a 14.0 landed