Bohea

Making a dashboard query scan 230× less data

A ClickHouse tuning demo you can run yourself: the same 50-million-row events table in a naive schema versus a tuned one, measured with the database's own query_log. A filtered dashboard query drops from scanning 1.9 GiB to about 8 MiB — roughly 230× less data, 16× faster — and a daily rollup gets 54× faster with a projection. One command rebuilds it from empty; a CI job re-runs it on every push and fails the build if the tuning ever regresses.

ClickHouseData WarehouseQuery TuningOLAPProven with query_log

The problem

An analytical table grows to tens or hundreds of millions of rows, and the dashboards on top of it slow to a crawl. Each query reads far more data than it needs, latency climbs, and — on a metered warehouse — the bill climbs with it. The usual response is "add more hardware," which pays to scan the same wasted bytes faster instead of scanning fewer of them.

The constraint: prove the win with numbers, not vibes

Tuning advice is easy to assert and hard to trust. So the whole thing is built to be measured and reproduced: identical data and identical queries on both schemas, the win read straight from query_log (bytes read, rows read, duration), and a single command that rebuilds the benchmark from an empty database so anyone can check the result themselves.

What moves the numbers

Why this is my kind of problem

Data-platform reliability is my center: most of six years of backend was building and operating ETL and storage under load — a 7-microservice cross-database migration, throughput taken from 50 to 5,000 QPS, a binlog-level recovery that restored 100% of lost data with zero downtime. The instinct is the same here: don't argue about performance, instrument it, prove the win with the database's own numbers, and put a gate around it so it can't silently rot.

Proof

Runnable, reproducible, and on video. The full benchmark is public on GitHub — the naive and tuned schemas, the queries, and the query_log numbers — and it rebuilds from empty with one command, with a GitHub Actions job re-running it on every push. There's a 3-minute walkthrough of it running live. The dataset is a generated 50M-row benchmark rather than a specific client's data; what it proves is the method and the measured result, which port straight onto a real warehouse.  Code →  ·  3-min walkthrough →

Where else this applies

Any analytical or OLAP workload where queries scan more than they should: product analytics, event pipelines, reporting warehouses, dashboards that got slow as the data grew. If a query feels slow and nobody can say exactly why, the first move is to measure what it actually reads — and then make it read far less.

When this approach doesn't apply

The one-line version, if you're passing this along

"He used the database's own log to show scan volume dropping 230×, then wrote a CI gate so it can't quietly come back."

If a machine you build needs an interface, a device connection, or data that has to land somewhere else, tell me what it's costing you now. You'll get an honest read on whether it's solvable, and usually something running to look at. Start here →

← All case studies