clickhouse-query-cost-estimator
A terminal CLI that estimates the cost of a ClickHouse SQL query before you regret running it, and helps you tune indexes afterwards.
╭──────────────────────────────────────────────────────────────╮
│ ClickHouse Query Cost Estimator v0.1.0 │
│ Connected to localhost:8123 · database: default · 23.8 │
╰──────────────────────────────────────────────────────────────╯
Cost Estimate (from EXPLAIN ESTIMATE)
Database Table Parts Est. Rows Marks
default orders 12 4.5M 550
Timing
Phase Time Notes
SQL Analyzer (EXPLAIN) 2.1 ms parsing + plan generation
Execution (client) 234.5 ms wall-clock including network
Execution (server) 228.3 ms server-side only
Execution Stats
Rows read 4.5M Bytes read 1.2 GB
Result rows 18.2K Peak memory 45.6 MB
── Index Suggestions ──────────────────────────────────────────
✓ created_at — already in ORDER BY
⚠ user_id — not in ORDER BY
ALTER TABLE default.orders
ADD INDEX idx_orders_user_id user_id
TYPE bloom_filter(0.01) GRANULARITY 4;
What it tells you
| Metric | Source |
|---|---|
| Estimated rows / parts / marks | EXPLAIN ESTIMATE |
| SQL analyzer time | time to run EXPLAIN PLAN (parsing + planning) |
| Execution time (client) | wall-clock including network round-trip |
| Execution time (server) | elapsed_ns from X-ClickHouse-Summary header |
| Rows / bytes read, peak memory | system.query_log after execution |
| Index suggestions | system.tables ORDER BY vs WHERE columns |
Installation
pip install chqce
Or, for local development:
pip install -e .
Usage
# Analyze a single query
chqce "SELECT count() FROM hits WHERE EventDate = today()"
# Interactive mode — paste any query, then type ; or GO to submit
chqce
# Custom connection
chqce --host my.ch.host --port 9123 --user admin --database analytics \
"SELECT count() FROM events WHERE user_id = 42"
# Estimate only — skip execution (safe for expensive/destructive queries)
chqce --no-execute "SELECT * FROM huge_table WHERE x > 0"
Large queries
For big, multi-line queries (hundreds or thousands of lines) you don't want to wrestle with shell quoting. Read the query from a file or pipe it in instead:
# From a file — the cleanest option for huge queries
chqce -f report.sql
# Piped via stdin
cat report.sql | chqce
chqce < report.sql
# If ClickHouse rejects it with a max_query_size error, raise the limit
chqce -f report.sql --max-query-size 1048576 # 1 MiB
The query source is resolved in this priority order:
--file/-f— read from a fileQUERYargument — passed on the command line- piped stdin — when input isn't a terminal
- interactive prompt — when nothing else is provided
The echoed query is truncated to the first 30 lines in the output, so a large query never buries the results.
Timeouts and resource limits
Heavy queries can hit server-side limits. The tool catches these, reports them clearly, and tells you which flag gets you unstuck:
# Abort the query after 5 minutes instead of waiting indefinitely
chqce -t 300 "SELECT ... a slow aggregation ..."
# Fix "AST is too big" (e.g. a giant IN (...) list)
chqce -f report.sql --max-ast-elements 500000
# Fix "Max query size exceeded"
chqce -f report.sql --max-query-size 1048576 # 1 MiB
When a query fails, the error is classified and shown with suggestions. For example, a timeout renders as:
╭──────────────────────────────────────────────────────────────╮
│ ✗ Execution error Query timed out │
│ Code: 159. DB::Exception: Timeout exceeded: elapsed 30 ... │
│ │
│ Suggestions │
│ The query exceeded its time budget. Try: │
│ • raise the limit: --timeout 600 (seconds, 0 = unlimited)│
│ • estimate without running: --no-execute │
│ • narrow the query with a WHERE filter or LIMIT │
╰──────────────────────────────────────────────────────────────╯
Recognized failures: timeout, AST too big, parser depth, query size, memory limit, and read-row/byte limits.
Options
| Flag | Env var | Default | Description |
|---|---|---|---|
--file / -f |
— | — | Read the query from a file (best for huge queries) |
--host / -H |
CLICKHOUSE_HOST |
localhost |
ClickHouse host |
--port / -p |
CLICKHOUSE_PORT |
8123 |
HTTP port |
--user / -u |
CLICKHOUSE_USER |
default |
Username |
--password / -P |
CLICKHOUSE_PASSWORD |
(empty) | Password |
--database / -d |
CLICKHOUSE_DATABASE |
default |
Default database |
--timeout / -t |
— | 0 (unlimited) |
Server-side max_execution_time in seconds |
--max-query-size |
— | (server default 262144) | Raise ClickHouse max_query_size for very large queries |
--max-ast-elements |
— | (server default 50000) | Raise ClickHouse max_ast_elements for queries with huge ASTs |
--no-execute |
— | false |
Skip actual execution; estimate only |
Interactive mode
Type or paste a multi-line query, then submit by:
- Ending the last line with
; - Typing
GOon its own line
Press Ctrl+C to exit.
How index suggestions work
- The query is parsed with sqlglot to extract WHERE-clause columns and condition types (equality, range, LIKE, IN).
- Each referenced table's
sorting_keyis fetched fromsystem.tables. - Columns not covered by the sort key get a skip-index
ALTER TABLEsuggestion, with the type chosen by condition and column type:
| Condition | Column type | Suggested index |
|---|---|---|
LIKE / ILIKE |
any | tokenbf_v1(32768, 3, 0) |
> / < / BETWEEN |
any | minmax |
= / IN |
String | bloom_filter(0.01) |
= / IN |
numeric / date | set(100) |
Requirements
- Python ≥ 3.10
- ClickHouse with HTTP interface enabled (default port 8123)
Development
Run the test suite (no ClickHouse server required — tests use a fake client):
pip install -e ".[test]" # or: pip install -r requirements-dev.txt
pytest
The tests live in tests/ and cover error classification, the estimator,
index suggestions, output formatting, connection settings, and the CLI.
Metadata
Release files for chqce 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| chqce-0.1.0.tar.gz | 21.5 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| chqce-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 37.5 kB
Release files / chqce-0.1.0.tar.gz
| Download URL | chqce-0.1.0.tar.gz |
|---|---|
| Size | 21.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
c26a0b126117bb13b7481ded0101ded0c035c6b287fcf6db07e49d1c7a6b545f
|
|
BLAKE2b-256 checksum How to use checksums |
b93b60f182b0825f02d8d8a681753e45b8647fc24a6d8a3c1ab4106a802dd79e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jun 6, 2026.
Transparency logRelease files / chqce-0.1.0-py3-none-any.whl
| Download URL | chqce-0.1.0-py3-none-any.whl |
|---|---|
| Size | 16.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
4d5dfe3cd8e3b7ae9f958ef4dd37260dba0f1bf5d48037ea2fb69703362df93e
|
|
BLAKE2b-256 checksum How to use checksums |
527e93f547399b5a8eef10ccfbbe9987e6a7a598cdd748b43f58a20e9eeb2a03
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jun 6, 2026.
Transparency log