Field note · December 7, 2025
The arithmetic behind a cheap query
Column pruning times partition pruning on a real schema, and the function call that quietly defeats both.
Query cost on a columnar store is mostly one number: bytes scanned. Here is that number worked out on ride-hail-trips.
Naming 3 of 10 columns cuts the scan to roughly 30.0%. Filtering to one of 365 days cuts it to 0.3%. Together — and they multiply — the query reads about 0.08% of what select * would.
-- reads every column, every day
select * from ride_hail_trips;
-- reads 3 columns, one day
select trip_id, pickup_at, borough
from ride_hail_trips
where pickup_at >= date '2023-06-01'
and pickup_at < date '2023-06-02';The second version is not a micro-optimisation. On a real warehouse those two queries differ by three orders of magnitude in cost, and the expensive one is the one that is easier to type.
The trap worth knowing: wrapping the partition column in a function — date(pickup_at) = '2023-06-01' — usually defeats pruning, because the engine can no longer reason about the raw column. Same result, full scan, no warning. Compare against a range on the bare column instead.
Read the bytes-scanned line in the plan before optimising anything else. It is usually the entire answer. Why your query costs what it costs has the rest.