# Qdrant Embedded и SQLite
## Откуда взялась SQLite?
SQLite — это **внутренняя деталь реализации Qdrant**, а не наш выбор.
При работе в **embedded-режиме** (без отдельного сервера) Qdrant использует SQLite для хранения:
- Payload-данных (метаданные векторов)
- ID-маппингов
- Служебной информации
Файл `storage.sqlite` создаётся автоматически в директории `qdrant_storage/`.
## Embedded vs Server режим
| Аспект | Embedded | Server |
|--------|----------|--------|
| Деплой | Простой, всё в одном процессе | Требует отдельного сервиса |
| Производительность | Достаточна для небольших коллекций | Лучше для больших объёмов |
| Очистка данных | Ручной VACUUM | Автоматическая сборка мусора |
| Масштабирование | Ограничено | Кластеризация, шардирование |
Мы используем embedded для упрощения деплоя — не нужно запускать отдельный Docker-контейнер или сервис Qdrant.
## Проблема с очисткой данных
При переиндексации нужно полностью очистить коллекцию. Qdrant предоставляет `delete_collection()`, но в embedded-режиме есть проблема:
**После удаления коллекции SQLite-файлы остаются и занимают место.**
Qdrant embedded:
- НЕ делает `VACUUM` автоматически
- НЕ освобождает дисковое пространство
- Новые данные пишутся поверх старых «пустых» страниц
## Почему лезем в SQLite напрямую?
В `QdrantAdapter.clear_and_compact()` мы делаем:
```python
# 1. Удаляем коллекцию через API
self.client.delete_collection(collection_name)
# 2. Закрываем клиент
self.close()
# 3. Напрямую чистим SQLite
conn = sqlite3.connect(str(sqlite_file))
cursor.execute("DROP TABLE IF EXISTS ...")
conn.execute("VACUUM")
```
Это **хак**, но необходимый — иначе база будет расти при каждой переиндексации.
## Как избавиться от прямой работы с SQLite?
### Вариант 1: Удалять директорию целиком (рекомендуется)
```python
def clear_and_compact(self, collection_name: str, vector_size: int):
self.close()
shutil.rmtree(self.path)
self.path.mkdir(parents=True)
self.client = QdrantClient(path=str(self.path))
self.create_collection(collection_name, vector_size)
```
Плюсы:
- Простой и надёжный код
- Гарантированно освобождает место
- Не зависит от внутренней реализации Qdrant
Минусы:
- Может быть проблема с блокировками файлов на Windows
### Вариант 2: Qdrant Server
Запустить Qdrant как отдельный сервис (Docker) и подключаться по HTTP:
```python
client = QdrantClient(host="localhost", port=6333)
```
Плюсы:
- Автоматическая сборка мусора
- Лучшая производительность на больших объёмах
- Персистентность данных независимо от приложения
Минусы:
- Усложняет деплой
- Дополнительный сервис для мониторинга
## Текущее состояние
Используем embedded + прямой VACUUM в SQLite. При появлении проблем с масштабированием или блокировками стоит рассмотреть переход на вариант 1 или 2.