Local-first CLI and MCP advisor for ClickHouse query optimization. Находит SQL-антипаттерны, показывает формально обоснованные rewrite-рекомендации, дополняет их retrieval-контекстом из KB и при необходимости оценивает влияние через
EXPLAIN ESTIMATE.
- рекомендации привязаны к
rule_id, tier и версии ClickHouse; - Tier
1A/1B/1Cявно отделяет формальные rewrite-правила от условных и приближённых; - retrieval advisory добавляет ссылки на документацию, но не заменяет rule engine;
EXPLAIN ESTIMATEможет показать оценку сокращения строк/marks безANALYZEи без чтения пользовательских данных;- MCP server позволяет вызывать тот же локальный анализ из Claude Desktop, Cursor, Continue и других агентов.
- 21+ правил и детекторов для ClickHouse SQL (
R-001…R-018,D-003,D-004,D-007) - version-aware filtering по
--ch-versionили автоопределению через--connect - console / JSON / Markdown отчёты
- режим
--mode explainс образовательными пояснениями - retrieval-based advisory через embedded Qdrant KB
- выбор embedding-модели при индексации KB
- optional
EXPLAIN ESTIMATEimpact summaries - stdio MCP server с tools и prompts
- synthetic benchmark и ablation experiment для embedding-моделей
git clone https://github.com/olyannaa/clickadvisor.git
cd clickadvisor
poetry install
poetry run chadvisor analyze --sql examples/bad_query.sqlpip install clickadvisor # когда пакет будет опубликован
chadvisor analyze --sql examples/bad_query.sqldocker run --rm -v $(pwd):/queries \
ghcr.io/username/clickadvisor:latest \
analyze --sql /queries/query.sqlpoetry run chadvisor analyze --sql query.sqlpoetry run chadvisor analyze --sql query.sql --ch-version 25.3poetry run chadvisor analyze --sql query.sql \
--connect http://host:8123 \
--ch-user default \
--ch-password secretpoetry run chadvisor analyze --sql query.sql --mode explainpoetry run chadvisor analyze --sql query.sql --output-format json
poetry run chadvisor analyze --sql query.sql --output-format markdownЕсли указан --connect, ClickAdvisor может выполнить EXPLAIN ESTIMATE для исходного SQL и rule rewrite (example_after) и добавить строку 📊 Влияние:
poetry run chadvisor analyze --sql query.sql \
--connect http://localhost:8123 \
--explain-estimateЭто не запускает ANALYZE и не читает пользовательские данные; используется оценка планировщика ClickHouse (rows, marks).
Индексация KB создаёт embedded Qdrant базу .qdrant_db из data/kb/chunks/:
poetry run chadvisor index-kbПовторная индексация:
poetry run chadvisor index-kb --reindexВыбор embedding-модели:
poetry run chadvisor index-kb --embedding-model multilingual-e5-small
poetry run chadvisor index-kb --embedding-model minilm-l6Доступные модели:
| Key | Model | Size | Notes |
|---|---|---|---|
multilingual-e5-small |
intfloat/multilingual-e5-small |
117 MB | default, multilingual, E5 prefixes |
minilm-l6 |
sentence-transformers/all-MiniLM-L6-v2 |
80 MB | english-only, faster, best MRR@3 on current English KB |
При наличии .qdrant_db команда analyze по умолчанию добавляет RAG-находки отдельной секцией 📚 Релевантная документация. Управление:
poetry run chadvisor analyze --sql query.sql --retrieval
poetry run chadvisor analyze --sql query.sql --no-retrievalClickAdvisor предоставляет stdio MCP server:
poetry run chadvisor mcp-serverПодробная инструкция для Claude Desktop, Cursor, Continue и других клиентов: docs/MCP.md.
MCP tools:
analyze_query— Markdown-отчёт для SQLanalyze_query_json— структурированный JSON без RAG-находокlist_rules— список правилdetect_ch_version— определение версии ClickHouse через HTTP API
MCP prompts:
analyzeexplain
| Rule ID | Описание | Tier |
|---|---|---|
R-001 |
COUNT(DISTINCT x) → uniqExact(x) |
1A |
R-002 |
COUNT(DISTINCT x) → advisory uniq(x) |
1B |
R-003 |
quantileExact(...) → advisory quantileTDigest(...) |
1B |
R-004 |
COUNT(*) FROM (SELECT DISTINCT ...) collapse |
1A |
R-005 |
toDate(col) = ... → datetime range |
1A |
R-006 |
toYYYYMM(...) / toStartOfMonth(...) → range |
1A |
R-007 |
toStartOfHour/Day/FifteenMinutes(...) → range |
1A |
R-008 |
redundant CAST(...) in filter |
1C |
R-009 |
singleton IN (...) → equality |
1A |
R-010 |
col = a OR col = b OR col = c → IN (...) |
1A |
R-011 |
non-aggregate predicate in HAVING → WHERE |
1C |
R-012 |
constant predicate elimination | 1A |
R-013 |
length(x) = 0 / > 0 / != 0 → empty/notEmpty |
1A |
R-014 |
advisory hash-based GROUP BY for long strings |
1B |
R-015 |
DISTINCT after equivalent GROUP BY removal |
1A |
R-016 |
ORDER BY in subquery without LIMIT |
1C |
R-017 |
subquery filter pushdown | 1A |
R-018 |
advisory UNION → UNION ALL |
1C |
D-003 |
top-level SELECT * detector |
detector |
D-004 |
missing LIMIT on non-aggregate top-level select |
detector |
D-007 |
costly FINAL modifier detector |
detector |
Synthetic benchmark:
poetry run python scripts/eval/run_benchmark.pyCurrent curated synthetic benchmark (lenient mode): precision/recall/F1 are expected to remain 1.00 for rule detection.
Embedding ablation:
poetry run python scripts/eval/ablation_embeddings.pyLatest 2000-chunk ablation reports MRR@3 over synthetic cases and prints a recommendation. On the English-heavy KB, all-MiniLM-L6-v2 had the best MRR@3, but the default remains multilingual E5; see docs/adr/ADR-013-embedding-model-selection.md.
SQL + Schema + optional EXPLAIN / CH version
↓
SQL Parser (sqlglot)
↓
┌──────────────────┐
│ Rule Engine │
│ ├─ Tier 1A: formally equivalent rewrites
│ ├─ Tier 1B: approximate / opt-in guidance
│ ├─ Tier 1C: conditional rewrites
│ └─ Detectors: antipattern detection
└──────────────────┘
↓
Version Filter + optional EXPLAIN ESTIMATE comparator
↓
optional Retrieval Advisor (Qdrant + embeddings)
↓
Report (console | JSON | Markdown | MCP)
poetry install
poetry run pytest -k 'not test_detect_version'
poetry run ruff check clickadvisor tests scripts
poetry run python scripts/eval/run_benchmark.pytests/integration/test_version.py::test_detect_version ожидает доступный ClickHouse HTTP endpoint на localhost:8123 с подходящими credentials.
