Проблемы производительности¶
Диагностика и оптимизация производительности Р13.Орбита.
Запросы выполняются медленно¶
Симптомы¶
- Обработка вопроса занимает > 30 секунд
- Таймауты при выполнении запросов
- CLI "висит" на этапе обработки
- API возвращает 504 Gateway Timeout
Причина¶
- Неэффективные SQL запросы к ClickHouse
- Большой объем обрабатываемых данных
- Медленный LLM провайдер
- Недостаточно ресурсов (CPU/память)
- Сетевая задержка к ClickHouse или LLM API
Диагностика¶
# 1. Проверьте использование ресурсов контейнером
docker stats orbita --no-stream
# 2. Проверьте логи для timing информации
docker logs orbita | grep -i "duration\|took\|elapsed"
# 3. Проверьте CPU и память на хосте
top
free -h
# 4. Проверьте сетевую задержку к ClickHouse
docker exec orbita ping -c 10 clickhouse
# 5. Проверьте latency к LLM API
time curl https://api.openai.com/v1/models \
-H "Authorization: Bearer $LLM_API_KEY"
# 6. Посмотрите какой SQL генерируется
docker logs orbita | grep "SELECT\|FROM\|WHERE"
Решение¶
Оптимизация 1: Ограничение результатов¶
# Добавьте в .env
nano .env
# Ограничьте количество строк в результате
QUERY_MAX_ROWS=1000 # По умолчанию может быть больше
# Перезапустите
docker restart orbita
Оптимизация 2: Увеличение ресурсов контейнера¶
# Остановите контейнер
docker stop orbita
docker rm orbita
# Запустите с увеличенными лимитами
docker run -d \
--name orbita \
--restart unless-stopped \
--cpus="2.0" \ # 2 CPU cores
--memory="4g" \ # 4GB RAM
--memory-swap="6g" \ # 6GB swap
-p 8000:8000 \
--env-file .env \
-v $(pwd)/domains:/app/domains \
-v $(pwd)/logs:/app/logs \
your-registry.company.com/orbita:latest
Оптимизация 3: Connection pooling¶
# Увеличьте размер пула подключений к ClickHouse
nano .env
CLICKHOUSE_POOL_SIZE=20 # Увеличьте с дефолтного 10
CLICKHOUSE_POOL_MAX_OVERFLOW=10
docker restart orbita
Оптимизация 4: Кеширование результатов¶
# Включите Redis для кеширования
nano .env
REDIS_URL=redis://redis:6379/0
CACHE_TTL=3600 # Кешировать на 1 час
# Запустите Redis если еще не запущен
docker-compose up -d redis
docker restart orbita
Оптимизация 5: Используйте более быструю LLM модель¶
nano .env
# Вместо gpt-4 используйте gpt-3.5-turbo (быстрее и дешевле)
LLM_MODEL=gpt-3.5-turbo
# Или используйте локальный Ollama для еще большей скорости
LLM_BASE_URL=http://host.docker.internal:11434
LLM_MODEL=llama3
docker restart orbita
Профилактика¶
- Используйте индексы в ClickHouse для частых запросов
- Ограничивайте временные диапазоны в вопросах
- Используйте агрегацию вместо детализированных данных
- Настройте monitoring для отслеживания performance
Высокое использование CPU¶
Симптомы¶
Причина¶
- Множество одновременных запросов
- Тяжелые вычисления (особенно при создании визуализаций)
- Неоптимальная работа LLM провайдера
- Memory leak или бесконечный цикл
Диагностика¶
# Проверьте загрузку CPU
docker stats orbita --no-stream
# Проверьте процессы внутри контейнера
docker exec orbita top -b -n 1
# Проверьте количество запросов
docker logs orbita | grep "POST /api/v1/queries" | wc -l
# Проверьте логи на наличие ошибок/циклов
docker logs orbita --tail 100 | grep -i "error\|retry\|attempt"
Решение¶
Ограничить CPU usage¶
docker update --cpus="1.5" orbita
# Ограничит контейнер до 1.5 CPU cores
# Или пересоздайте контейнер с лимитом
docker stop orbita
docker rm orbita
docker run -d \
--name orbita \
--cpus="1.5" \
--cpu-shares=1024 \
-p 8000:8000 \
--env-file .env \
-v $(pwd)/domains:/app/domains \
your-registry.company.com/orbita:latest
Включить rate limiting¶
nano .env
# Ограничьте количество запросов
API_RATE_LIMIT_ENABLED=true
API_RATE_LIMIT_REQUESTS=10 # 10 запросов
API_RATE_LIMIT_WINDOW=60 # за 60 секунд
docker restart orbita
Использовать worker процессы¶
# Увеличьте количество Uvicorn workers для лучшего распределения нагрузки
nano .env
API_WORKERS=4 # По умолчанию 1
docker restart orbita
Профилактика¶
- Настройте rate limiting
- Используйте load balancer для распределения нагрузки
- Мониторьте CPU usage
Высокое использование памяти¶
Симптомы¶
- Out of Memory (OOM) killer завершает контейнер
- Контейнер постоянно перезапускается
Причина¶
- Большие датасеты загружаются в память
- Memory leak в приложении
- Слишком много одновременных запросов
- Кеширование слишком большого объема данных
Диагностика¶
# Проверьте использование памяти
docker stats orbita --no-stream
# Проверьте логи OOM killer
dmesg | grep -i "killed process"
# Проверьте размер сохраненных датасетов
docker exec orbita du -sh ~/.orbita/
# Мониторьте память в реальном времени
docker stats orbita
Решение¶
Увеличить лимит памяти¶
docker update --memory="6g" orbita
# Или пересоздайте контейнер
docker stop orbita
docker rm orbita
docker run -d \
--name orbita \
--memory="6g" \
--memory-swap="8g" \
--memory-reservation="4g" \
-p 8000:8000 \
--env-file .env \
-v $(pwd)/domains:/app/domains \
your-registry.company.com/orbita:latest
Ограничить размер результатов¶
nano .env
# Ограничить количество строк
QUERY_MAX_ROWS=1000
# Ограничить размер ответа в байтах
QUERY_MAX_RESULT_SIZE_MB=100 # 100MB макс
docker restart orbita
Очистить старые данные¶
# Очистить старые датасеты
docker exec orbita python -c "
from orbita_service.dataset import DatasetService
from datetime import datetime, timedelta
service = DatasetService()
cutoff = datetime.now() - timedelta(days=30)
service.cleanup_old_datasets(cutoff)
"
# Или удалить вручную через SQL
docker exec postgres-metadata psql -U orbita_user orbita -c "
DELETE FROM datasets WHERE created_at < NOW() - INTERVAL '30 days';
"
Профилактика¶
- Настройте автоматическую очистку старых датасетов
- Используйте pagination для больших результатов
- Не храните датасеты в памяти, используйте БД
Медленная генерация SQL¶
Симптомы¶
- LLM долго генерирует SQL запрос (> 10 секунд)
- Генерируется неоптимальный SQL
Причина¶
- Используется медленная модель (GPT-4 vs GPT-3.5)
- Слишком большой context window
- Неоптимизированные few-shot примеры в доменах
Диагностика¶
# Проверьте какая модель используется
cat .env | grep LLM_MODEL
# Проверьте latency к LLM API
time curl https://api.openai.com/v1/chat/completions \
-H "Authorization: Bearer $LLM_API_KEY" \
-H "Content-Type: application/json" \
-d '{"model":"gpt-4","messages":[{"role":"user","content":"test"}]}'
# Проверьте размер контекста в конфигурации доменов
wc -l domains/*.yaml
Решение¶
Используйте более быструю модель¶
nano .env
# GPT-3.5-turbo быстрее GPT-4
LLM_MODEL=gpt-3.5-turbo
# Или используйте локальный Ollama
LLM_BASE_URL=http://host.docker.internal:11434
LLM_MODEL=llama3
docker restart orbita
Оптимизируйте few-shot примеры¶
# domains/ecommerce.yaml
# Оставьте только самые релевантные примеры (3-5 штук)
few_shot_examples:
- question: "покажи продажи за последний месяц"
sql: "SELECT date, SUM(amount) FROM orders WHERE date >= today() - INTERVAL 1 MONTH GROUP BY date"
# ... оставьте только ключевые примеры
Уменьшите temperature¶
nano .env
# Меньше temperature = более детерминированные и быстрые ответы
LLM_TEMPERATURE=0.1 # Вместо 0.7
docker restart orbita
Профилактика¶
- Используйте кеширование сгенерированных SQL для похожих вопросов
- Оптимизируйте few-shot examples
- Используйте fine-tuned модели (если доступно)
Медленное выполнение SQL в ClickHouse¶
Симптомы¶
- SQL генерируется быстро, но выполняется долго (> 30 секунд)
Причина¶
- Неоптимальный SQL запрос
- Отсутствие индексов в ClickHouse
- Полное сканирование таблицы
- Большой объем данных без фильтрации
Диагностика¶
# Проверьте SQL в логах
docker logs orbita | grep "Executing SQL"
# Выполните EXPLAIN в ClickHouse
clickhouse-client --query "
EXPLAIN SELECT * FROM ecommerce.orders WHERE date >= '2024-01-01'
"
# Проверьте размер таблицы
clickhouse-client --query "
SELECT
table,
formatReadableSize(sum(bytes)) as size,
sum(rows) as rows
FROM system.parts
WHERE database = 'ecommerce'
GROUP BY table
"
# Проверьте медленные запросы
clickhouse-client --query "
SELECT
query,
query_duration_ms,
read_rows
FROM system.query_log
WHERE type = 'QueryFinish'
AND query_duration_ms > 1000
ORDER BY query_duration_ms DESC
LIMIT 10
"
Решение¶
Создать индексы в ClickHouse¶
-- Добавьте индексы на часто используемые колонки
ALTER TABLE ecommerce.orders ADD INDEX idx_date (date) TYPE minmax GRANULARITY 1;
ALTER TABLE ecommerce.orders ADD INDEX idx_customer (customer_id) TYPE set(1000) GRANULARITY 1;
-- Материализуйте индексы
ALTER TABLE ecommerce.orders MATERIALIZE INDEX idx_date;
ALTER TABLE ecommerce.orders MATERIALIZE INDEX idx_customer;
Оптимизировать таблицы ClickHouse¶
-- Используйте правильный engine и партиционирование
CREATE TABLE ecommerce.orders_optimized
(
date Date,
order_id UInt64,
customer_id UInt64,
amount Decimal(10,2)
)
ENGINE = MergeTree()
PARTITION BY toYYYYMM(date)
ORDER BY (date, customer_id)
SETTINGS index_granularity = 8192;
-- Перенесите данные
INSERT INTO ecommerce.orders_optimized SELECT * FROM ecommerce.orders;
Ограничить временной диапазон¶
Научите пользователей формулировать вопросы с временными ограничениями:
Профилактика¶
- Создавайте индексы на ключевые колонки
- Используйте партиционирование по дате
- Регулярно запускайте OPTIMIZE TABLE
- Мониторьте медленные запросы
Долгое создание визуализаций¶
Симптомы¶
- Создание графиков занимает > 20 секунд
- Таймауты при генерации визуализаций
Причина¶
- Слишком много точек данных на графике
- Неоптимальная библиотека визуализации
- Недостаточно ресурсов для matplotlib/plotly
Диагностика¶
# Проверьте размер датасета
docker exec orbita python -c "
from orbita_service.dataset import DatasetService
service = DatasetService()
dataset = service.get_dataset('dataset_id')
print(f'Rows: {len(dataset.data)}')
"
# Проверьте логи для timing
docker logs orbita | grep "chart\|visualization"
Решение¶
Ограничить количество точек данных¶
Использовать агрегацию¶
Для больших датасетов используйте агрегацию перед визуализацией:
Использовать более быструю библиотеку¶
nano .env
# Используйте matplotlib вместо plotly для статических графиков
CHART_BACKEND=matplotlib # Быстрее чем plotly
docker restart orbita
Профилактика¶
- Агрегируйте данные перед визуализацией
- Используйте sampling для очень больших датасетов
- Кешируйте сгенерированные графики
Контрольный список оптимизации¶
При проблемах с производительностью проверьте:
Инфраструктура¶
- Достаточно CPU (минимум 2 cores)
- Достаточно RAM (минимум 4GB)
- SSD диски (не HDD)
- Стабильная сеть к ClickHouse
Конфигурация¶
- Connection pooling настроен
- Limits установлены (QUERY_MAX_ROWS)
- Rate limiting включен
- Кеширование настроено (Redis)
ClickHouse¶
- Индексы созданы
- Таблицы оптимизированы
- Партиционирование настроено
- OPTIMIZE TABLE регулярно запускается
LLM¶
- Используется оптимальная модель
- Temperature понижена
- Few-shot примеры минимизированы
- Timeout увеличен при необходимости
Мониторинг производительности¶
Метрики для отслеживания¶
# 1. Время обработки запросов
docker logs orbita | grep "Request took" | awk '{print $NF}'
# 2. Использование ресурсов
docker stats orbita --no-stream
# 3. Количество запросов в секунду
docker logs orbita | grep "POST /api/v1/queries" | wc -l
# 4. Slow queries в ClickHouse
clickhouse-client --query "
SELECT query, query_duration_ms
FROM system.query_log
WHERE query_duration_ms > 5000
ORDER BY query_duration_ms DESC LIMIT 10
"
Настройка Prometheus (опционально)¶
Если используете мониторинг через Prometheus:
# docker-compose.yml
services:
prometheus:
image: prom/prometheus
ports:
- "9090:9090"
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
grafana:
image: grafana/grafana
ports:
- "3000:3000"
depends_on:
- prometheus
Следующие шаги¶
- Диагностика - подробная диагностика для выявления bottlenecks
- Проблемы подключения - если проблемы с сетевой задержкой
- Конфигурация - настройки для оптимальной производительности