Skip to main content

Welcome to a Grasp lesson

Create a free account to keep studying and create your own study path.

Lesson 26

Estimating Predicate Selectivity with Histograms

Recommended resources

Hello! Welcome back to our module on Query Optimization.

In our last lesson, we established the foundation of cost-based optimization: estimating the cardinality of intermediate results. We saw how simple statistics (|R|, V(A, R)) and basic formulas allow an optimizer to make initial guesses, but we also highlighted their major flaw: the assumption of uniform data distribution. Real-world data is often skewed, which can lead these simple estimates to be wildly inaccurate.

Today, we'll address that problem head-on. This lesson will focus on histograms, which are the database optimizer's primary tool for modeling non-uniform data. Your learning outcome is to describe how equi-width and equi-depth histograms are used to estimate predicate selectivity. By the end of this session, you'll understand the internal mechanics of how a database gets a much more accurate picture of your data's content to choose a better execution plan.

From Uniformity to Distribution: The Need for Histograms

As we discussed, assuming that all values in a column are equally common is a convenient but often incorrect simplification. If we have a status column where 'active' accounts for 99% of rows and 'archived' for 1%, using the formula sel = 1 / V(A,R) for a query WHERE status = 'archived' would be off by orders of magnitude.

Storing the exact frequency of every single value would provide perfect estimates, but this is impractical. For a column with millions of distinct values, the statistics would be as large as the column itself!

Histograms offer a practical middle ground. They are data structures that approximate the distribution of values in a column by grouping them into a fixed number of buckets. This provides a compressed summary that is much more accurate than a simple average but far smaller than storing exact counts.

F2023 #14 - Query Planning & Optimization (CMU Intro to Database Systems)

Let's start with a high-level overview from the CMU course on why histograms are essential and how they provide a more compact and accurate representation of data.

Please watch from 1:07:09 to 1:11:15. As you watch, focus on these key ideas: The impracticality of storing exact counts for every distinct value. The concept of grouping values into buckets as a compression strategy. The introduction of the two main types of histograms: equi-width and equi-depth.


The Two Flavors: Equi-Width vs. Equi-Depth

As the video introduced, there are two primary strategies for creating histogram buckets. Their structures are a direct result of how they handle the trade-off between implementation simplicity and accuracy in the face of data skew.

Comparison of Equi-Width and Equi-Depth Histograms
This image visually contrasts the two main histogram types. The **equi-width** histogram (left) has buckets with equal value ranges but varying heights (counts). The **equi-depth** histogram (right) has buckets with varying value ranges but roughly equal heights (counts), adapting to the data's density.

Let's formalize these concepts.

1. Equi-Width Histograms

In an equi-width histogram, the entire range of values for a column (from min_val to max_val) is divided into a set number of buckets, each covering an identical width or range of values.

  • Structure: Each bucket stores a count of the number of tuples whose values fall within its specific range.
  • Pros: Very simple to construct and maintain. The bucket for any given value can be found with a quick arithmetic calculation.
  • Cons: Ineffective for skewed data. If a few values are extremely common, they will be grouped into a single bucket with a very high count, while many other buckets might be sparse or empty. Information about the distribution within that high-density bucket is lost.

2. Equi-Depth Histograms (or Equi-Height)

In an equi-depth histogram, the goal is for every bucket to hold approximately the same number of tuples.

  • Structure: The bucket boundaries are adjusted so that each bucket represents a different width in the value range. Dense regions of data will have narrow buckets, while sparse regions will have wide buckets.
  • Pros: Adapts gracefully to data skew. It provides more detailed information (i.e., more buckets) for the most frequent value ranges, which is precisely where better estimates are needed. This generally leads to better accuracy.
  • Cons: More complex to construct, as it requires sorting the column values (or a sample of them) to determine the bucket boundaries.

Query Planning & Optimization Part 2

These lecture slides from CMU provide clear, illustrated definitions of both histogram types. Pay close attention to the diagrams showing how the same data is partitioned differently by each method.

Please read slides 21 and 22 (labeled 'EQUI-WIDTH HISTOGRAM' and 'EQUI-DEPTH HISTOGRAMS'). Compare the bucket boundaries and counts in the example visuals for each type.

Because of their superior accuracy on skewed data, equi-depth histograms are more commonly used in modern database systems.


Using Histograms to Estimate Selectivity

Now for the core of the lesson: how does the optimizer use these structures to calculate selectivity? The general principle is to locate the relevant bucket(s) and then assume a uniform distribution within that bucket.

A. Estimating for Equality Predicates (WHERE col = value)

  1. The optimizer identifies which bucket the value falls into.
  2. It retrieves the total count of items in that bucket.
  3. It assumes the items are uniformly distributed within the bucket's value range.
  4. The estimated count for the specific value is calculated as (count in bucket) / (number of distinct values in bucket). If the number of distinct values is not stored, it's often approximated from the range.
  5. Selectivity = (Estimated Count) / (Total Tuples in Table)

B. Estimating for Range Predicates (WHERE col > value)

  1. The optimizer identifies the bucket where the value lies.
  2. Partial Bucket Calculation: For this bucket, it calculates the fraction of the range that satisfies the predicate. For example, if the bucket covers values [30, 40] and the predicate is > 35, it assumes (40 - 35) / (40 - 30) = 50% of the rows in that bucket match. This is a form of linear interpolation.
  3. Full Bucket Calculation: It adds the full counts of all buckets that are completely within the range (i.e., all buckets whose lower bound is greater than value).
  4. The total estimated count is the sum from the partial bucket and all full buckets.
  5. Selectivity = (Total Estimated Count) / (Total Tuples in Table)

Query Planning & Optimization Part 2

Let's return to the CMU slides for a concrete application of these rules. They walk through examples for both equality and range predicates using an equi-depth histogram.

Please review slides 31 through 33, which cover selectivity for single selection conditions. Pay attention to how they handle: An equality predicate (age = 9) falling into a bucket [9, 13] (Slide 31). A range predicate (age >= 7) that covers a partial bucket and several full buckets (Slide 33).

Test your understanding!

A table employees has 1,000,000 rows. You have the following 4-bucket equi-depth histogram on the salary column. Each bucket contains 250,000 rows.

  • Bucket 1: [30000, 50000]
  • Bucket 2: [50001, 65000]
  • Bucket 3: [65001, 90000]
  • Bucket 4: [90001, 200000]

Estimate the number of rows returned by the query SELECT * FROM employees WHERE salary > 80000;. Assume values are continuous and uniformly distributed within each bucket.

Show answer
  1. Identify the buckets: The predicate salary > 80000 involves Bucket 3 and Bucket 4.

  2. Calculate the partial contribution from Bucket 3:

    • The value 80000 falls within Bucket 3, which has the range [65001, 90000].
    • The width of this bucket's range is 90000 - 65001 = 24999.
    • The portion of the range that is > 80000 is [80001, 90000], which has a width of 10000.
    • The fraction of the bucket that matches is 10000 / 24999 ≈ 0.4.
    • The estimated number of rows from this bucket is 0.4 * 250,000 = 100,000.
  3. Calculate the full contribution from Bucket 4:

    • Bucket 4's range [90001, 200000] is entirely greater than 80000.
    • The number of rows from this bucket is its full count: 250,000.
  4. Sum the contributions:

    • Total estimated rows = (Rows from Bucket 3) + (Rows from Bucket 4)
    • Total estimated rows = 100,000 + 250,000 = 350,000.

The optimizer would estimate that approximately 350,000 rows will be returned.


A Practical Look: Histograms in PostgreSQL

To ground this theory in a real system, let's look at how a popular open-source database like PostgreSQL handles this. Real-world implementations often add a layer of sophistication. For extremely skewed data, even an equi-depth histogram might not be ideal. A few values can be so common that they deserve special treatment.

PostgreSQL combines two techniques:

  1. Most Common Values (MCV) List: It stores a separate list of the most frequent values and their exact frequencies.
  2. Histogram: It then builds a histogram on the remaining values that are not in the MCV list.

When estimating selectivity, the optimizer first checks if the value is in the MCV list. If so, it uses the exact frequency. If not, it uses the histogram as described above.

Queries in PostgreSQL: 2. Statistics

This technical blog post from Postgres Professional gives an excellent, applied view of how histograms are used in practice. This aligns with your goal of understanding system internals from an engineering perspective.

Please read the section titled 'Histogram'. Focus on understanding the following points: How the histogram (histogram_bounds) is used in conjunction with the MCV list. The example calculation for seat_no > '30C'. Note how the final estimate combines the fraction from the MCV list with the fraction from the histogram. The mention of using 'linear interpolation' when a value doesn't fall exactly on a bucket boundary, which is the same principle we discussed for partial buckets.

This hybrid approach allows the optimizer to be highly accurate for the most common values (which often have the biggest impact on query cost) while still having a good general model for the rest of the data distribution.


Conclusion

You have now explored the primary mechanism that database optimizers use to overcome the flawed assumption of uniform data distribution. Understanding histograms is key to appreciating how a database can intelligently estimate the costs of its operations.

Key Takeaways:

  • Histograms approximate the data distribution in a column by grouping values into buckets.
  • Equi-width histograms have buckets of equal value range, making them simple but less effective for skewed data.
  • Equi-depth histograms have buckets with roughly equal numbers of tuples, making them better at adapting to data skew and generally more accurate.
  • Selectivity is estimated by locating the relevant bucket(s) and assuming uniform distribution within a bucket, using linear interpolation for partial buckets.
  • Real systems like PostgreSQL often use a hybrid approach, combining Most Common Values (MCV) lists for very frequent items with histograms for the rest of the data.

Preview of the Next Lesson

So far, we have focused on estimating the cardinality of SELECT operations on a single table. The next major challenge is estimating the result size of a JOIN. In our next lesson, we will learn how to estimate the cardinality of join operations using foreign key statistics, which is another critical input for choosing the most efficient join order and algorithm.