Skip to main content

Count-Min Sketch: How to Find Hot Data with Just a Few KB?

When a system needs to discover its most frequently accessed data, the obvious approach is to keep a counter for every item. Every time a key appears, increment its counter. Later, inspect or sort those counters to find the most popular keys.

That approach is simple and exact, but it becomes expensive when the set of possible keys is large. A key might be a URL, product identifier, user ID, search term, database record, cache entry, or event type. In a large stream, there may be millions or billions of distinct keys. Storing an exact counter for every one can consume far more memory than the application can afford.

A Count-Min Sketch provides a compact alternative. It uses a small two-dimensional table of counters and several hash functions to estimate how often a key has appeared. The structure does not store a separate record for every key. Instead, it maps each key into several table positions and combines the resulting counters when a query arrives.

The central trade-off is straightforward:

  • An exact dictionary uses more memory but can return exact counts.
  • A Count-Min Sketch uses a fixed amount of memory but returns approximate counts.
  • Its estimates are designed not to underestimate the true frequency. They may be too large because different keys can share table positions.

This makes the structure useful when the question is not, What is the exact count of every item? but rather, Which items are unusually frequent? or How often has this item appeared, approximately?

The frequency-estimation problem

Imagine a continuous stream of accesses:

home-page, image-17, home-page, product-42, image-17, home-page, ...

A monitoring or data-processing system may want to answer questions such as:

  • How often was a particular URL accessed?
  • Which product IDs receive the most requests?
  • Which database keys are hot?
  • Which event types dominate a stream?
  • Has a particular identifier appeared more often than a threshold?

The stream may be too large to retain in full. It may also be unbounded: events continue arriving indefinitely. Even if the system can process every event, keeping a full exact map of all distinct keys may be impractical.

A Count-Min Sketch is designed for this streaming setting. It processes each item as it arrives, maintains a bounded amount of state, and later estimates the frequency of a requested key.

Let the true frequency of a key x be written as f(x). The sketch stores a compact summary of the stream rather than the stream itself. After processing the data, a query for x produces an estimate written as f_hat(x).

Under the ordinary nonnegative-counter model, the estimate has one-sided error:

f_hat(x) >= f(x)

The reason is how the counters are updated. Each selected counter receives every increment belonging to x, plus possibly some increments belonging to other keys that collide with x. Those additional contributions can increase the estimate, but the sketch does not subtract a contribution that genuinely belonged to x.

This property is valuable for filtering and threshold decisions. It is also a limitation: an estimate is not automatically an exact count.

The two-dimensional counter table

The basic structure is a table with several rows and several columns. Each row is associated with a different hash function. The columns represent counter positions.

A small sketch might conceptually look like this:

column 0 column 1 column 2 column 3 column 4
row 0 0 4 1 0 2
row 1 3 0 2 1 1
row 2 1 2 0 5 0
row 3 0 1 3 0 2

The table has two important dimensions:

  • Width: the number of columns in each row.
  • Depth: the number of rows, and therefore the number of hash functions.

For a key x, each hash function chooses one column in its corresponding row:

hash_0(x) -> column in row 0
hash_1(x) -> column in row 1
hash_2(x) -> column in row 2
...

The table starts with zeroes. When a key arrives, the sketch computes all of its row-specific positions and increments one counter per row. A query computes the same positions, reads one counter from each row, and returns the minimum of those values.

That gives the name Count-Min Sketch:

  • It counts items in a compact table.
  • It uses the minimum of several candidate counts.

The table contains aggregate information. It does not contain a normal key-to-count entry for every input key.

Updating the sketch

Suppose a key x arrives once. The update operation is:

  1. Hash x with the first hash function.
  2. Use the result to select a column in row zero.
  3. Increment that counter.
  4. Repeat for every remaining row and hash function.

If the sketch has depth d, one update increments exactly d counters.

Pseudocode for the operation is:

update(x):
for row from 0 to depth - 1:
column = hash[row](x) mod width
table[row][column] += 1

The modulo operation maps a hash value into the available column range. In a practical implementation, the row-specific mappings may be produced by several hash functions, differently seeded versions of a hash function, or another deterministic method that gives varied positions for different rows.

Consider a sketch with three rows and eight columns. For a key named product-42, suppose its positions are:

row 0 -> column 3
row 1 -> column 6
row 2 -> column 1

Updating product-42 increments exactly these three cells:

table[0][3] += 1
table[1][6] += 1
table[2][1] += 1

If the same key appears again, the same three cells are incremented again. The table does not need to store the text product-42. It only needs to hash that key consistently during updates and later queries.

The update is therefore compact and predictable. The sketch performs a fixed number of counter increments for every event, regardless of how many distinct keys have already appeared.

Querying a frequency

To estimate the frequency of a key, the sketch follows the same hash paths but reads instead of increments:

estimate(x):
candidates = empty list

for row from 0 to depth - 1:
column = hash[row](x) mod width
candidates.append(table[row][column])

return minimum(candidates)

Suppose a key has been observed ten times. Its three selected counters might be:

row 0 -> 10
row 1 -> 13
row 2 -> 10

The estimate is:

min(10, 13, 10) = 10

The value 13 may be larger because another key used the same cell in row one. The minimum ignores that larger contaminated value when another row gives a cleaner count.

If all three counters are larger than the true frequency, then collisions affected every row. Increasing the width reduces the chance that this happens. Increasing the depth gives more independent opportunities for at least one row to have relatively little collision noise.

Why collisions are unavoidable

The table is deliberately smaller than the set of possible keys. If there are more possible keys than columns, multiple keys must map to the same column in at least some rows. This is the familiar hash-collision problem.

For example, suppose two different keys map to the same position in row zero:

hash_0(alpha) -> column 4
hash_0(beta) -> column 4

If alpha appears five times and beta appears seven times, the counter at row zero, column four receives twelve increments from these two keys. A query for alpha sees at least those contributions in that row, so that row suggests a count of twelve rather than five.

The same pair of keys may not collide in another row:

hash_1(alpha) -> column 2
hash_1(beta) -> column 6

In that row, alpha has a counter that does not include beta's seven occurrences. The minimum across rows can therefore produce a better estimate.

Collisions are not an implementation failure. They are the mechanism that allows many possible keys to share a small amount of memory. The design goal is to control the effect of collisions rather than eliminate them completely.

The width controls how much sharing occurs within each row. The depth provides multiple differently hashed views of the same stream. A key can collide in one view while avoiding a collision in another.

Why the minimum is used

It may seem natural to average the counters from all rows. However, the Count-Min Sketch uses the minimum because each selected counter is an upper-bound-style candidate.

For a queried key x, the counter selected in a particular row contains:

  1. Every update belonging to x.
  2. Zero or more updates belonging to other keys that collided with x in that row.

Therefore, each selected counter is at least the true frequency of x. Some rows may be heavily affected by collisions, while another row may be relatively clean. Taking the minimum chooses the least inflated candidate.

An average would allow heavily contaminated rows to raise the result even when a cleaner row is available. A maximum would be even more vulnerable to collisions. The minimum matches the sketch's one-sided counting behavior.

This does not mean that the minimum is always exact. Consider a key with true frequency 3 whose selected counters are 4, 8, and 5. The result is 4, so the estimate remains inflated. The minimum only reduces the effect of collisions; it cannot undo collisions that occur in every row.

Width, depth, and the accuracy trade-off

The sketch's memory and accuracy are controlled primarily by width and depth.

Width

Increasing the width creates more columns in every row. That spreads keys across more locations and reduces the amount of sharing between unrelated keys. Fewer collisions generally means smaller overestimates.

The cost is memory. If the counter size remains the same, doubling the width approximately doubles the number of counters.

Depth

Increasing the depth creates more rows and more hash functions. A queried key gets more candidate counters, and the minimum has more chances to find a row with limited collision noise.

The cost is also computational. Every update and every query must process more rows. The total number of stored counters also increases.

The practical balance

A very narrow sketch is memory-efficient but may produce large overestimates. A very deep sketch can improve the chance of finding a relatively clean row, but it increases update work, query work, and memory consumption.

The appropriate dimensions depend on the acceptable error, the stream volume, the number of distinct keys, the distribution of frequencies, and the memory budget. The important engineering property is that the sketch does not grow with the number of distinct keys. Once its dimensions are selected, its table size is fixed.

This bounded-memory behavior is the reason a sketch can remain useful for an extremely large stream. The billionth event uses the same number of table operations as the first event, assuming the configuration and key representation remain unchanged.

A small worked example

Consider a sketch with three rows and five columns. Assume the hash positions are as follows:

row 0 row 1 row 2
apple 1 3 0
banana 1 1 4
carrot 2 3 0

Now process this stream:

apple, banana, apple, carrot, apple

The true frequencies are:

apple -> 3
banana -> 1
carrot -> 1

The updates affect these cells:

  • apple increments row zero column one, row one column three, and row two column zero three times.
  • banana increments row zero column one, row one column one, and row two column four once.
  • carrot increments row zero column two, row one column three, and row two column zero once.

The resulting table is:

column 0 column 1 column 2 column 3 column 4
row 0 0 4 1 0 1
row 1 0 1 0 4 0
row 2 4 1 0 0 1

To estimate apple, read positions (row 0, column 1), (row 1, column 3), and (row 2, column 0):

4, 4, 4

The estimate is 4, although the true frequency is 3. The extra counts come from collisions. banana shares row zero column one with apple, while carrot shares row one column three and row two column zero with apple.

This example demonstrates an important subtlety. Even with several rows, a small table can cause every candidate counter to be inflated. A larger width would make simultaneous collisions less likely.

It also shows why the table should be viewed as a compressed summary. The value 4 in a cell does not say which key generated those four updates. It only records the total number of increments assigned to that position.

Finding hot data

A Count-Min Sketch can estimate the frequency of a key that you already know. Finding the hottest keys is a related but different problem.

The sketch's counter table contains positions, not a complete list of original keys. A counter value by itself does not identify which key caused the increments. Therefore, a sketch alone cannot usually enumerate every key in descending frequency order.

A practical hot-data design often combines the sketch with a limited candidate set. As events arrive:

  1. Update the sketch for the incoming key.
  2. Estimate the key's current frequency.
  3. Compare the estimate with the current hot-key candidates.
  4. Keep promising keys for later exact or approximate ranking.

The sketch acts as a compact frequency estimator, while a separate small structure remembers the identities of candidates. This distinction is essential: the sketch compresses counts, but it does not preserve all key names.

For example, a service might observe request keys and maintain a bounded candidate list. When a new key's estimated count becomes competitive, the system can place it in that list. The list can then be used to report likely hot data, while the sketch continues to summarize the full stream.

The exact candidate-management policy is a separate design choice. The Count-Min Sketch supplies frequency estimates; another component decides which key identities are worth retaining. If exact values are required for selected candidates, the system can track those candidates in an exact map after promotion.

This hybrid approach is often more practical than trying to use the sketch as a complete top-items database. The sketch handles the large stream, while the auxiliary structure focuses memory on a small number of important keys.

Space and time complexity

Let w be the width and d be the depth.

The table contains:

d * w counters

Therefore, the space complexity is:

O(d * w)

This space is bounded by the configured dimensions rather than by the number of distinct keys in the stream. If each counter uses a fixed number of bytes, the memory footprint is proportional to the number of table cells.

Each update hashes the key and increments one counter in every row. Its time complexity is:

O(d)

Each frequency query reads one counter in every row and computes a minimum. Its time complexity is also:

O(d)

These costs are attractive for streaming systems because they remain independent of the total number of processed events. The structure does perform multiple hash computations and counter accesses per event, but that fixed work replaces potentially large per-key storage.

The total memory footprint can be estimated from the table dimensions and counter size. For example, a table with d * w cells and a fixed-width integer counter uses approximately that many cells multiplied by the counter's byte width, subject to implementation details such as alignment and storage layout.

Choosing counter types

Every table cell stores a count, so the counter type matters. A small integer type saves memory but has a limited maximum value. A larger type supports larger cumulative frequencies but increases the table size.

When selecting a counter representation, consider:

  • The maximum expected count for one cell.
  • Whether the stream is reset periodically.
  • Whether counters can saturate at a maximum value.
  • Whether overflow would produce unacceptable estimates.
  • The total table size under the chosen integer width.

Saturating counters stop increasing at their maximum rather than wrapping around. Saturation can prevent an overflow from turning a large count into a small or negative value, but it also means the estimate loses information after the limit is reached.

The right choice depends on the application. A short observation window may need smaller counters than a sketch that accumulates events for a long time. A long-lived cumulative sketch must account for the possibility that frequently updated cells grow much faster than the average cell.

Counter overflow should be treated as a correctness concern, not merely a low-level implementation detail. A wrapped counter can invalidate the one-sided interpretation of the estimate. A saturation policy preserves a safer monotonic behavior, although it cannot preserve exact magnitude beyond the counter limit.

Hashing considerations

Hashing is central to the sketch. Updates and queries must use exactly the same mapping rules. If an update and a later query hash the same key differently, the query will read unrelated cells and return an invalid estimate.

A multi-row sketch needs row-specific positions. This can be implemented with several hash functions or with one hash process that derives multiple row positions from a key and different seeds. The important behavior is that different rows should distribute keys differently enough to make simultaneous collisions unlikely.

Useful implementation considerations include:

  • Use a deterministic encoding for keys.
  • Ensure the encoding distinguishes different keys correctly.
  • Keep hash seeds stable for the lifetime of a sketch.
  • Use a consistent method for mapping hash values to columns.
  • Consider the cost of hashing when updates arrive at very high rates.

Poorly distributed hashing can concentrate many keys in a small portion of the table. That increases collisions and makes estimates less useful, even if the table has a reasonable nominal width.

Key encoding also matters. If keys are strings, byte sequences, or structured records, the update path and query path must serialize them identically. Two distinct logical keys should not accidentally receive the same representation, and the same logical key should not receive different representations at different points in the system.

When sketches are merged, hashing compatibility becomes even more important. All sketches being combined must use compatible dimensions, row ordering, hash functions, seeds, and key interpretation.

Threshold decisions and one-sided error

Many systems do not need an exact count. They need a decision such as:

Is this key used at least T times?

The Count-Min Sketch can be useful here, but its overestimation must be considered. If the sketch reports a value below the threshold, the true count cannot be above that reported value under the usual nonnegative-update model. If the sketch reports a value above the threshold, the true count may still be lower because collisions could have contributed extra increments.

Thus, an estimate can produce a false positive for a threshold test, but the basic sketch's one-sided behavior avoids the opposite kind of error under ordinary assumptions. Whether that is acceptable depends on the application.

For example, a cache-warming system might tolerate investigating a few extra candidates. A billing system that requires exact counts would not use the sketch as its final source of truth.

A useful pattern is to use the sketch as a fast filter:

  1. Reject clearly low-frequency keys.
  2. Send promising keys to a more precise data structure or slower exact process.
  3. Use exact tracking only for the small number of candidates that matter.

This combines the bounded memory of the sketch with higher accuracy where it is most valuable. The sketch does not need to be perfect for every key if it can efficiently narrow a huge stream down to a manageable set of candidates.

Resetting and time windows

A cumulative sketch summarizes all updates since it was created or last cleared. Many operational questions are time-based instead:

  • Which keys were hot during the last minute?
  • Which endpoints received the most requests this hour?
  • Which records became popular recently?

A sketch can be used for a defined observation window by periodically resetting it. Another approach is to maintain multiple sketches for adjacent time intervals and rotate them according to the desired window.

The correct windowing strategy depends on the question being asked. A cumulative count answers a lifetime-style frequency question, while a reset or rotating sketch answers a recent-activity question.

Resetting also has a practical benefit: it prevents counters from growing indefinitely and may allow smaller counter types when each window has a known maximum volume. However, resetting discards historical information, so the schedule must match the monitoring objective.

Windowing can also affect hot-data interpretation. An item that was popular over the entire lifetime of a service may not be hot during the current interval. Conversely, a newly popular item may be hidden by a cumulative history dominated by older events. The sketch configuration and reset policy should therefore reflect whether the application cares about total activity or recent activity.

Merging sketches

A useful property of Count-Min Sketches is that compatible summaries can be combined. Suppose two processes observe separate portions of the same kind of stream. If their sketches have the same dimensions, compatible counter representations, and matching hash functions and seeds, their tables can be added cell by cell.

Conceptually:

merge(A, B):
for every row and column:
A.table[row][column] += B.table[row][column]

The resulting table represents the combined updates because every cell contains the sum of the contributions from both input streams. A later query uses the common hashing configuration and takes the minimum across rows as usual.

This supports distributed processing. Multiple workers can summarize local events, and a coordinator can combine the summaries without receiving every original event. The amount of data exchanged can be the size of the compact tables rather than the size of all observed records.

Compatibility is critical. Sketches with different dimensions or hash mappings cannot simply be added and expected to produce a meaningful result. Even if two tables have the same apparent shape, different hash seeds or key encodings can make their cells represent different sets of keys.

The merge operation also reinforces the idea that a sketch is a summary of updates. Addition combines summaries naturally because both input tables record accumulated counter increments.

Comparing with an exact hash map

An exact hash map stores a key and its counter for each distinct item. It is the right choice when:

  • The number of distinct keys is small enough.
  • Exact results are mandatory.
  • The application must enumerate all keys.
  • Counts must support arbitrary updates or deletions.
  • Memory consumption is not the main constraint.

A Count-Min Sketch is attractive when:

  • The input is a large or unbounded stream.
  • Memory must remain fixed and small.
  • Approximate frequency is sufficient.
  • The system needs fast per-event updates.
  • The application mainly cares about frequent or suspicious items.
  • Distributed summaries need to be merged.

There is also a hybrid design. An exact map can track a small set of important keys, while a sketch summarizes the long tail. The sketch can help decide which keys deserve promotion into the exact map.

The choice is not simply between accurate and inaccurate. It is a choice between different resource profiles and error models. An exact map spends memory on key identities and exact counters. A sketch spends a fixed amount of memory and accepts collision-based overestimation.

An exact map is also naturally better for enumeration. If the requirement is to list every distinct key, a sketch cannot replace the map because the sketch has intentionally discarded key identity information. If the requirement is only to ask about a known key or filter likely frequent keys, the sketch's compact summary may be sufficient.

What the sketch can and cannot tell you

The Count-Min Sketch is well suited to frequency estimation, but it is not a general-purpose replacement for a dictionary.

It can provide a compact estimate for a key when the key can be hashed consistently. It can support decisions based on approximate frequency, such as identifying likely popular items or testing whether activity is above a threshold.

It does not, by itself, provide a complete mapping from keys to counts. The table contains aggregated counters, and multiple keys may contribute to the same counter. Once updates have been combined, the original identities cannot generally be reconstructed from the table alone.

This means the sketch is a summary, not an archive. If an application needs to display the names of the most frequent keys, it must preserve candidate identities elsewhere or obtain them through another mechanism.

The basic nonnegative counting sketch is also primarily insertion-oriented. Arbitrary deletion is difficult because a shared counter does not reveal how much of its value came from one key and how much came from other keys. Subtracting a key's update from shared counters could remove contributions that belong to unrelated keys.

Special variants and additional assumptions can support other update models, but those should not be confused with the basic Count-Min Sketch. For a standard implementation, treat updates as nonnegative increments and design the surrounding system accordingly.

Common implementation mistakes

Several mistakes can undermine an otherwise correct design.

Treating the estimate as exact

A sketch estimate can be inflated by collisions. Code should not silently present it as an exact count when users or downstream systems rely on exactness.

Forgetting to use the same hashing configuration

The update and query paths must agree on hash functions, seeds, key encoding, width, and row ordering. Any mismatch makes the result meaningless.

Assuming the table identifies keys

The counters store aggregated contributions. They do not provide a built-in list of the keys that produced them. Hot-key reporting needs a separate identity-tracking strategy.

Making the table too narrow

A tiny table may have so many collisions that most estimates are heavily inflated. The memory saving can be outweighed by poor usefulness.

Ignoring counter overflow

Counters have finite ranges. Overflow or an unsuitable saturation policy can corrupt estimates, especially for long-lived sketches.

Using it for exact accounting

Approximate summaries are valuable for monitoring, ranking, and filtering. They should not replace exact ledgers when every unit must be accounted for precisely.

Mixing incompatible sketches

Cell-wise merging assumes compatible dimensions and hash mappings. Combining unrelated configurations does not produce a valid summary of the union of their streams.

Forgetting the time window

A cumulative sketch and a recent-activity sketch answer different questions. If the application cares about current hot data, the structure needs a suitable reset or rotation policy.

A practical design workflow

When considering a Count-Min Sketch, begin with the decision the system must make. Do not start with the table dimensions. Ask whether the application needs an exact count, an approximate count, a threshold signal, or a list of top candidates.

Next, identify the stream characteristics:

  • What is the event rate?
  • How many distinct keys may appear?
  • Is the stream bounded or continuous?
  • Is the frequency cumulative or windowed?
  • Must summaries be merged across workers?
  • How much overestimation is acceptable?

Then decide how key identities will be handled. If the goal is to find hot data, the sketch alone is not enough to name the hot items. Plan a candidate structure, sampling method, or other identity-preserving component.

After that, select a memory budget and choose width and depth. Measure the resulting behavior on representative traffic. Synthetic data can demonstrate the mechanics, but real key distributions matter: a stream with a few very frequent keys behaves differently from a nearly uniform stream.

Finally, monitor the sketch as an approximate component. Validate decisions against an exact sample or a separate reference process where possible. This helps reveal whether the configured dimensions, counter types, hash behavior, and time window are suitable for the workload.

A useful testing plan includes both ordinary and adversarial-looking distributions. Test repeated access to a small set of keys, many mostly unique keys, and mixtures of frequent and infrequent keys. Observe not only average estimates but also the behavior of the keys that matter to the application. The sketch's usefulness is determined by the decisions it supports, not just by its table size.

Intuitive summary

A Count-Min Sketch can be understood as several independent compressed views of the same stream.

Each view is a row. In each view, a hash function assigns every key to one counter. An update increments one counter per view. A query follows the key through every view and receives several candidate counts. Since other keys can only add noise to a selected counter, the smallest candidate is used as the estimate.

The sketch saves memory by allowing keys to share counters. That sharing causes overestimation, but multiple rows reduce the chance that every view is badly contaminated for the same key.

The most important properties are:

  • Fixed memory: the table size is chosen in advance.
  • Fast updates: one counter is updated per row.
  • Fast queries: one counter is read per row, followed by a minimum.
  • Approximate results: collisions can raise estimates.
  • No automatic key enumeration: names of hot items require separate tracking.
  • Mergeability: compatible sketches can summarize separate stream partitions and later be combined.

The structure is best viewed as a compact signal about frequency. It trades the ability to remember every key separately for a predictable amount of memory and a fixed amount of work per event.

Final practical takeaways

Use a Count-Min Sketch when a large stream must be summarized with a small, predictable memory footprint and approximate frequency is acceptable. Its multi-hash two-dimensional counter table turns each event into a small number of counter increments. A later query hashes the same key again and takes the minimum of the corresponding counters.

The structure is especially useful for identifying likely hot data, filtering low-frequency items, monitoring activity, and building compact distributed summaries. Its main cost is controlled approximation: collisions mean that estimates may be higher than the true counts.

Remember the boundary between estimation and identity. The sketch can tell you how frequently a known key appears, but it does not automatically retain the complete set of keys needed to list the hottest items. For hot-data discovery, pair it with a small candidate-tracking component or an exact structure for selected keys.

In short, the Count-Min Sketch exchanges per-key storage for a fixed table, exact counts for bounded approximation, and complete identity retention for scalable frequency signals. When those trade-offs match the problem, a very small amount of memory can provide useful information about an enormous stream.