Changing how much data exists
Why do data-reduction mechanisms dominate, and why is their limit the interface's vocabulary?
The earlier articles chose an execution strategy for a computation whose input size was fixed. Every win was a constant factor. The constants were large, but they were constants. The mechanisms in this article are categorically different. They do not choose a strategy. They change how much data there is to process. That is why they dominate. A better join order may win 10×. Not reading 99% of the files wins 100×. The two wins multiply; they do not compete.
All the mechanisms in this article are the same act. Each one takes a fragment of the query (a predicate, a column list, a row limit, a set of join keys) and transports it downward across an interface until it reaches a layer that can decline to produce data.
- Predicate pushdown moves a filter into the scan, then into the file decoder, then into a comparison against the file footer, then into a remote system.
- Projection pushdown moves a column list into the file reader.
- Top-N pushdown moves a bound into a heap, and then into a threshold.
- Runtime filters create a predicate that did not exist in the query and send it sideways.
So the real subject of this article is not optimization. It is interface design. The limit is not physical and not informational. It is linguistic: what vocabulary does the layer below agree to understand?
Two questions that sort the mechanisms
A second distinction matters as much, because it separates mechanisms with very different risk. Ask: where does the information come from, and what does the mechanism do with it?
| Prove irrelevance (do not read) | Defer reading (read later, or less) | |
|---|---|---|
| From the query text | Partition pruning, file and row-group skipping | Projection pushdown, LIMIT |
| From catalog metadata (the stored description of the tables) | Constraint-based elimination, metadata-only answers | — |
| From this query's own execution | Dynamic partition pruning, runtime filters | Top-N threshold feedback, late materialization |
The left column is conservative and safe in a precise sense: it can only produce false positives. You may read a block that you did not need. You will never skip a block that you did need. The right column proves nothing. It changes when work happens, and its risk is that the reordering costs more than it saves.
This "safe direction" is the sharpest contrast with the planning articles. Cardinality estimation had no safe side, so its errors were unbounded. Data skipping has a safe side, so every engine adopts it aggressively. Nobody has ever been paged because a zone map (a stored min/max summary of a block) was too conservative.
Some terms used in this article
- Parquet is a columnar file format. A file is split into row groups (for example 10,000 or 1,000,000 rows). Inside a row group, each column is stored on its own, in pages. A footer at the end of the file stores, for each row group and column: the row count, the minimum, the maximum and the null count. These are the statistics.
- Pruning means skipping whole partitions or files. Skipping usually means skipping row groups or pages inside a file that you do open.
- A predicate is a condition in a
WHEREclause. A predicate is sargable when the engine can use it directly against stored values (dt = '2024-01-01') and not when the column is wrapped in a function (date(ts) = '2024-01-01'). - A Bloom filter is a small bit-array structure that answers "is this value in the set?". It may say "yes" wrongly (a false positive), but it never says "no" wrongly. So a "no" is a proof.