Интеллектуальная система анализа и оптимизации SQL-запросов в реляционных БД с использованием методов ИИ.
Система не просто «переписывает SQL через нейросеть»: ИИ — один компонент конвейера SQL Parser → Schema → Execution Plan → Rule Engine → AI → Safety → Validation → Equivalence → Benchmark → Score → Dataset. Любое улучшение подтверждается измерениями на реальной БД; без подключения система не показывает ни времени, ни ускорения.
| Модуль | Что делает | Файл |
|---|---|---|
| SQL Parser | AST (sqlglot): тип, таблицы, JOIN, WHERE, GROUP/ORDER BY, CTE, подзапросы (в т.ч. коррелированные), агрегаты, функции | backend/app/services/sql_parser.py |
| Schema Analyzer | схема из DDL (офлайн) или из живой БД: колонки, типы, индексы, PK/FK, число строк, размер | schema_ddl.py, connectors.py |
| Rule Engine | 16 детерминированных правил: функция над колонкой, LIKE '%…', OR по разным колонкам, NOT IN, коррелированные подзапросы, несовпадение типов, отсутствующий индекс, сортировка без индекса, большой OFFSET, декартово произведение, = NULL, ORDER BY RAND(), SELECT * … |
rules.py |
| Rule-based rewriter | безопасные эквивалентные преобразования без ИИ (YEAR/DATE/EXTRACT → диапазон) — baseline для экспериментов | rewriter.py |
| Execution Plan Analyzer | MySQL EXPLAIN FORMAT=JSON, PostgreSQL EXPLAIN (ANALYZE, BUFFERS, FORMAT JSON) → единое дерево; full scan, filesort, temporary, nested loop, ошибка оценки строк |
explain.py |
| AI-модуль | структурированный JSON-контекст, версионируемые промпты, строгий JSON-ответ, провайдеры GigaChat / YandexGPT / OpenAI-совместимые | services/ai/ |
| Safety Engine | только один read-only SELECT; блокирует DML/DDL, SELECT … INTO, FOR UPDATE, опасные функции, executable-комментарии, модифицирующие CTE |
safety.py |
| Валидация ответа ИИ | SYNTAX_ERROR, WRONG_TABLE, WRONG_COLUMN, INDEX_HALLUCINATION, SCHEMA_HALLUCINATION, DANGEROUS_QUERY, INVALID_RESPONSE — до выполнения | ai/optimizer.py |
| Equivalence | мультимножество строк (checksum), число колонок, порядок при ORDER BY; при расхождении — REJECT и примеры отличающихся строк |
benchmark.py |
| Benchmark | прогрев + N прогонов, чередование исходного и нового запроса; медиана/среднее/min/max/σ, rows examined (MySQL Handler_read_*, PG из ANALYZE), буферы | benchmark.py |
| Score и Confidence | Optimization Score 0–100 (веса в backend/config/scoring.json), AI Confidence из измеренных факторов, а не из самооценки модели |
scoring.py |
| Хранилище | запросы, версии, запуски, планы, бенчмарки, промпты и сырые ответы моделей, рекомендации индексов; экспорт CSV/XLSX/JSON | db.py, main.py |
| Research Mode | датасеты запросов, фоновые эксперименты «датасет × модели», сравнение моделей, базовая линия без ИИ, продолжение прерванных экспериментов | backend/app/research/ |
| Научный отчёт | параметры воспроизводимости, сводная таблица моделей, bootstrap-ДИ медианы ускорения, разбивка по категориям, типы ошибок, методика; HTML (печать в PDF), Markdown, CSV/XLSX/JSON | research/report.py |
| Консоль | запросы к своей базе (автодополнение по схеме, Ctrl+Enter, первые 500 строк, график, CSV, история и избранное); «Спроси базу» — вопрос на русском → SQL моделью с самоисправлением по ошибке СУБД | workbench.py, pages/Console.tsx |
| Знакомство с базой | выбор рабочей схемы; модель описывает базу, сущности и связи и предлагает готовые запросы, каждый проверяется через EXPLAIN; анализ сохраняется | workbench.py, components/DbIntro.tsx |
| Аудит базы | нет первичного ключа, внешний ключ без индекса, лишние и неиспользуемые индексы, дата в тексте, деньги во float, нет статистики — с оценкой и SQL исправлений | workbench.py |
| Медленные запросы | топ запросов по суммарному времени из pg_stat_statements / performance_schema, оптимизация в один клик |
connectors.py |
| ER-диаграмма и описание | схема связей (перетаскивание, PNG) и словарь данных в Word по ГОСТ 2.105 с описаниями от модели | ErDiagram.tsx, workbench.py |
| Веб-интерфейс | стартовая страница с чек-листом готовности, консоль, анализ запроса (Monaco), сравнение запросов, эксперименты, базы данных, история, обзор, встроенная инструкция по установке | frontend/ |
Все запросы к анализируемой БД выполняются в READ ONLY транзакции с таймаутом. Рекомендуется пользователь только с правом SELECT: система проверяет права и предупреждает, если их больше. Индексы не создаются автоматически.
Проще всего — через Docker, одной кнопкой. Нужен только Docker Desktop. Двойной щелчок по Запустить.cmd
в папке проекта: собираются и запускаются программа и демонстрационные БД, открывается браузер
(http://localhost:8080). Остановить.cmd — остановка, история анализов сохраняется. Ключи моделей берутся из
backend/.env, если он есть; базы на этом компьютере подключаются как обычно — по адресу 127.0.0.1.
То же без Windows: docker compose -f docker/docker-compose.yml up -d --build.
Для разработки нужны Python 3.11+, Node.js 20+, Docker Desktop (для демонстрационных БД), Git.
Windows — двумя командами (из папки проекта, в PowerShell):
powershell -ExecutionPolicy Bypass -File scripts\setup.ps1 # один раз: библиотеки, пакеты, демо-БД
powershell -ExecutionPolicy Bypass -File scripts\start.ps1 # каждый раз: БД, сервер, интерфейс, браузерПодробная пошаговая инструкция с настройкой GigaChat и локальной модели — в самой программе, раздел «Установка и помощь».
Вручную (любая ОС):
# 1. Тестовые БД (MySQL 8.4 :3307 и PostgreSQL 16 :5434, база shop, пользователь optimizer_ro/optimizer_ro)
docker compose -f docker/docker-compose.yml up -d mysql postgres
# 2. Backend
cd backend
python -m venv .venv
.venv\Scripts\pip install -r requirements.txt
copy .env.example .env # и при желании указать ключи LLM
.venv\Scripts\python -m uvicorn app.main:app --port 8000
# 3. Frontend
cd frontend
npm install
npm run dev # http://localhost:5173API-документация: http://localhost:8000/docs
В разделе «Базы данных» есть кнопки-пресеты для демо-MySQL и демо-PostgreSQL.
| Провайдер | Настройка в backend/.env |
id модели |
|---|---|---|
| GigaChat (Сбер) | GIGACHAT_AUTH_KEY, при ошибке SSL — GIGACHAT_CA_BUNDLE (сертификат НУЦ Минцифры) |
gigachat:GigaChat-2-Max |
| YandexGPT | YANDEX_API_KEY, YANDEX_FOLDER_ID |
yandex:yandexgpt/latest |
| DeepSeek / OpenRouter / Ollama / LM Studio | OPENAI_BASE_URL, OPENAI_API_KEY, OPENAI_MODELS, OPENAI_PROVIDER_NAME |
<provider>:<model> |
Новый провайдер добавляется подклассом LLMProvider (backend/app/services/ai/providers.py).
Промпты хранятся как файлы backend/app/services/ai/prompts/<id>.json. Для каждого запуска в БД сохраняются id промпта, его SHA-256, полный текст промпта и сырой ответ модели.
Раздел «Эксперименты» в интерфейсе или POST /api/experiments:
- Выберите подключение, датасет и модели. Встроенные датасеты:
shop-bench-v1(40 запросов: 15 категорий антипаттернов и контрольная группа уже оптимальных запросов) иshop-bench-mini-v1(по одному запросу на категорию). Свои датасеты импортируются списком SELECT-запросов. - Для каждой пары «запрос × модель» выполняется полный конвейер: анализ → кандидат → проверки → эквивалентность → бенчмарк. Модели идут во внутреннем цикле, поэтому кандидаты для одного запроса измеряются в близкое время.
baseline:rule-based— детерминированная базовая линия без ИИ, проходит те же проверки. С ней сравниваются LLM.- Исходы: Улучшено (результат совпал, ускорение ≥ 1,05x), Без изменений, Ухудшено (результат совпал, но медленнее более чем на 5%), Некорректно (синтаксис, схема, безопасность, изменение результата), Сбой вызова (инфраструктура LLM, не считается ошибкой модели).
- Отчёт:
GET /api/experiments/{id}/report(HTML, печать в PDF),/report.md,/export?format=csv|xlsx|json.
Для каждого эксперимента сохраняются: experiment_id, dataset_version, database_seed, application_version, модели и их параметры, prompt_version и SHA-256 промпта, версия СУБД, время начала и окончания.
Не запускайте два эксперимента одновременно и не нагружайте машину во время прогона: бенчмарк измеряет реальное время.
cd backend
.venv\Scripts\python -m pytest -q # unit + интеграционные (интеграционные пропускаются без docker)
.venv\Scripts\python scripts\smoke_test.py # прогон демо-запросов через запущенный APIИнтеграционные тесты проверяют полный AI-цикл на обеих СУБД с подставной моделью:
корректная оптимизация принимается, изменение результата отклоняется (RESULT_CHANGED),
выдуманная колонка отклоняется до выполнения (WRONG_COLUMN).
Медиана прогонов, время на клиенте. Данные детерминированы (seed v1): 100 тыс. пользователей, 500 тыс. заказов, 1,5 млн позиций.
| Запрос | СУБД | До | После | Ускорение | Просмотрено строк | Результат |
|---|---|---|---|---|---|---|
DATE(created_at) = '2025-03-15' |
MySQL 8.4 | 89 мс | 2,7 мс | 33x | 500 002 → 204 | совпал |
YEAR(created_at) = 2024 … LIMIT 50 |
MySQL 8.4 | 197 мс | 3,5 мс | 56x | 128 261 → 142 | совпал |
DATE(created_at) = … |
PostgreSQL 16 | 58 мс | 4,8 мс | 12x | 500 001 → 203 | совпал |
EXTRACT(YEAR …) = 2024 … LIMIT 50 |
PostgreSQL 16 | 39 мс | 4,5 мс | 8,8x | 128 260 → 142 | совпал |
отчёт по категориям, YEAR(o.created_at) = 2025 |
MySQL 8.4 | 140 мс | 185 мс | 0,76x | 525 980 → 100 204 | совпал |
| то же | PostgreSQL 16 | 83 мс | 169 мс | 0,49x | 522 267 → 91 359 | совпал |
Последние две строки показывают, зачем нужна проверка измерением. Переписывание стало «sargable», и строк просматривается в 5 раз меньше, но оптимизатор выбрал худший план соединения, и запрос замедлился. Система фиксирует это как регресс и не засчитывает как улучшение.
40 запросов, прогрев 2, прогонов 5. Отчёты: /api/experiments/1/report (MySQL), /api/experiments/2/report (PostgreSQL).
| MySQL 8.4 | PostgreSQL 16 | |
|---|---|---|
| Улучшено / без изменений / ухудшено / некорректно | 7 / 29 / 4 / 0 | 9 / 29 / 2 / 0 |
| Предложено изменений | 11 из 40 | 11 из 40 |
| Медиана ускорения (95% bootstrap-ДИ) | 33,6x (0,93–37,2x) | 11,5x (4,2–16,1x) |
| Геометрическое среднее ускорения | 10,3x | 6,3x |
| Максимальное ускорение | 106x | 24,9x |
| Контрольная группа (оптимальные запросы) | не затронута | не затронута |
Одно и то же эквивалентное преобразование YEAR(created_at) = N → диапазон дат в агрегирующем запросе ускоряет PostgreSQL в 4,2–4,6 раза, а MySQL замедляет (0,85–0,95x). Для отчёта с JOIN замедление на обеих СУБД (0,5–0,9x). Правило, «правильное» по учебнику, не универсально: без измерения на конкретной СУБД его применять нельзя.
Qwen2.5-Coder-7B (локально через Ollama, CPU) и baseline:rule-based; MySQL 8.4, shop-bench-mini-v1 (16 запросов, по одному на категорию); прогрев 2, прогонов 5.
| Qwen2.5-Coder-7B | Базовая линия | |
|---|---|---|
| Улучшено / без изменений / ухудшено / некорректно | 4 / 11 / 0 / 1 | 2 / 13 / 1 / 0 |
| Предложено изменений | 5 из 16 | 4 из 16 |
| Медиана ускорения эквивалентных кандидатов (95% ДИ) | 18,6x (1,2–55,1x) | 18,2x (0,8–53,4x) |
| Контрольная группа | не затронута | не затронута |
Модель нашла улучшения там, где правил нет (DISTINCT + JOIN, OR по разным колонкам). Один её вариант потерял условие отбора: вернул 100 000 строк вместо 1 500 и работал в 33 раза медленнее. Система проверки автоматически отклонила его как RESULT_CHANGED.
| № | Что проверялось | Главный результат |
|---|---|---|
| 4, 11 | абляция: план выполнения в контексте модели (Qwen, GigaChat-2-Pro) | значимого влияния нет, различия меньше разброса между прогонами |
| 5, 6 | Qwen2.5-Coder-7B против правил, 40 запросов, MySQL и PostgreSQL | сопоставимое число улучшений; модель находит преобразования вне правил |
| 7, 8 | GigaChat-2, -Pro, -Max, Qwen и правила, 80 задач на участника | GigaChat-2-Pro — 29 улучшений из 80 (правила — 17); чем чаще модель переписывает, тем больше и улучшений, и ошибок |
| 9, 10 | повторы эксперимента 7 для GigaChat-2-Pro и -Max | число улучшений стабильно, но набор улучшенных запросов меняется от прогона к прогону |
Дополнительно: оценка стоимости плана от самой СУБД угадывает направление изменения скорости в 79 % случаев —
замеры ею не заменить. Все 944 записи экспериментов — в открытом датасете dataset/ (DOI 10.5281/zenodo.22982517).
| Материал | Где | Как собрать |
|---|---|---|
| Отчёт о НИР (ГОСТ 7.32-2017), 67 с. | docs/nir/ |
python make_figures.py, charts2.py, diagrams.py, diagrams2.py, затем node build_report.js |
| Статьи и тезисы | docs/articles/ |
node build_articles.js |
| Технический отчёт «Архитектура» | docs/techreport/ |
node build_techreport.js |
| Презентация доклада | docs/talk/ |
python build_talk.py |
| Отчёт «GigaChat в оптимизации SQL» | docs/gigachat/ |
python build_gigachat_report.py |
| Эксперимент «ИИ против человека» | docs/human_study/ |
задания node build_study.js, оценка evaluate_humans.py |
| Открытый датасет | dataset/ |
python backend/scripts/export_dataset.py |
Все документы собираются из результатов экспериментов в базе программы, поэтому цифры в них согласованы.
PDF получаются через Microsoft Word (docs/nir/word_finalize.ps1) или Microsoft Edge в фоновом режиме.
backend/
app/
main.py HTTP API (FastAPI)
models.py доменные модели (Pydantic)
db.py хранилище результатов (SQLAlchemy)
services/
sql_parser.py rules.py rewriter.py safety.py schema_ddl.py
connectors.py explain.py benchmark.py scoring.py pipeline.py
ai/ providers.py optimizer.py prompts/optimizer-v1.json
config/scoring.json веса Optimization Score и AI Confidence
tests/ unit и интеграционные тесты
scripts/smoke_test.py
frontend/ React + TypeScript + Vite + Tailwind + Monaco
docker/ MySQL 8.4 и PostgreSQL 16 с демо-БД shop
- Эквивалентность проверяется эмпирически, на текущих данных, а не формально. Если ключ ORDER BY не уникален, различие в порядке строк выдаётся как предупреждение.
- Время измеряется на клиенте и включает передачу результата по сети.
- Рекомендованные индексы не применяются: бенчмарк отражает текущую схему. Проверку через гипотетические индексы (HypoPG) можно добавить позже.
MIT — см. LICENSE.
Яковлев А. С. AI Database Optimizer и SQL Optimization Dataset. – 2026. – DOI: 10.5281/zenodo.22982517.
DOI 10.5281/zenodo.22982517 всегда указывает на последнюю версию; версии 1.0.0 и 1.1.0 — 10.5281/zenodo.22982518 и 10.5281/zenodo.22984197.