Definition · Bloom filterA Bloom filter for a set of n keys is an array of m bits together with k hash functions. Inserting a key sets the k bits it hashes to. A query reports possibly present if all k of its bits are set, and certainly absent if any one of them is clear.
The second answer is exact. The false-positive rate p is the probability that a key which was never inserted nevertheless finds all k of its bits set by other keys.
At the k that minimises the rate, the space needed is about m/n = log₂(1/p)/ln 2 bits a key and the hash count is about k = log₂(1/p). This lesson states those two and uses them to size filters. The derivation, the exact form (1 − (1 − 1/m)^(kn))^k under the idealisation that the hashes are independent, the optimal k = (m/n)·ln 2, and the rule that a Bloom filter supports no deletion all belong to “Bloom Filters” on the Algorithms path, which owns them and proves them.
The independence from n is the part worth pausing on, because it is the reason a filter is a practical thing to build. A billion keys at one per cent is 1.20 GB; two billion keys at one per cent is 2.40 GB, and both are 9.5851 bits a key. Nothing about the filter gets relatively worse as the set grows, which is unusual enough that people assume it must be false.
bits a key = log₂(1/p) / ln 2 1/ln 2 = 1.442695…
p = 1/10 log₂(10) = 3.3219 → 4.7925 bits a key
p = 1/100 log₂(100) = 6.6439 → 9.5851 bits a key
p = 1/1 000 log₂(1000) = 9.9658 → 14.3776 bits a key
n = 10⁹ at p = 1/100 m = 9 585 058 378 bits = 1.20 GB, k = 7
n = 2×10⁹ at the same p = 2.40 GB, still 9.5851 a key
9.585, not 9.57
The figure usually quoted for one per cent is 9.57 bits a key, and it comes from writing the constant as 1.44. The constant is 1/ln 2 = 1.442695…, and at p = 1/100 the two produce 9.5851 and 9.5672 — a gap of 0.0179 bits a key, which is about 2.2 MB over a billion keys. That is small, and it is the wrong kind of small to leave unexplained on a page whose subject is exact counting. The lab prints both columns side by side and says which constant produced which, so the difference is visible rather than argued about.
Both columns are approximations, and so is everything derived from them. The bits-per-key figure is a logarithm and the false-positive estimate is an exponential; neither returns a fraction, and the lab labels every figure that inherits the rounding. Where an exact answer still exists it shows one: at m = 64, n = 8, k = 5 the exact rate is 0.02230073 and the approximation gives 0.02167922, so the approximation is optimistic by about three per cent of itself at that size. It gets better as m grows, which is why it is safe at the sizes anyone actually builds.
What a filter does to a log-structured tree
A lookup that misses has to try every level, which “Write Amplification in LSM Trees” priced at RA ≈ L. Put a filter on each level and the lookup consults memory first: on the level that holds the key it goes to disk as before, and on each of the other L − 1 levels it goes to disk only on a false positive. So the expected probes are 1 + (L − 1)p, which at L = 5 and p = 1/100 is 26/25 = 1.0400 — and that figure is exact, because p is a target you chose and L is a count.
Choosing p is choosing how many of the L − 1 useless probes you are willing to keep. One in ten leaves 1.40 probes at 4.79 bits a key; one in a hundred leaves 1.04 at 9.59; one in a thousand leaves 1.004 at 14.38. The cost is linear in the digits of 1/p and the benefit falls off a cliff after the first few, which is why most engines sit at one per cent and stop.
And a filter is only worth anything to a workload that asks for keys that are not there. A lookup that hits still reads the level holding its key, and the filter saved it nothing. What 1.20 GB bought over a billion keys was four probes out of five on misses, so the value of the filter is proportional to the miss rate — which is a property of the workload and has to be measured, not assumed.