# armdb QA
## Можно ли хранить несколько коллекций в одном файле?
Да, теоретически можно хранить несколько коллекций в одном наборе shard-файлов,
но это уже не текущая модель `database per collection`, а общий storage engine с
логическими коллекциями.
Сейчас модель явно обратная:
- `armdb/src/lib.rs` фиксирует `one tree = one database directory`.
- `Db::tree_path()` кладет коллекцию в отдельный путь `name:vN`.
- Каждый `Engine::open()` открывает `config.shard_count` отдельных shard-директорий.
- Для Bitcask свежий shard держит минимум два file descriptor: active write file
и active read file. После rotations immutable files тоже остаются открытыми для
чтения.
- `__seq` дополнительно использует FixedMap с 4 shard'ами.
Грубая оценка для Bitcask:
```text
fd ~= collections * shards * 2
+ immutable rotated files
+ __seq fixed shards
+ rpc/socket/прочие fd процесса
```
Чтобы хранить несколько коллекций в одном физическом логе, нужно добавить
`collection_id` в record/log format и recovery, оставить отдельные in-memory
indexes per collection, а физический append-log сделать общим per shard. Тогда
range, prefix, CAS, delete и typed API функционально сохраняются.
Но "без потерь" это не бесплатная замена:
- общий shard writer даст больше contention между горячими коллекциями;
- compaction станет сложнее, потому что live/dead данные разных коллекций будут
смешаны в одних files;
- migrations, drop collection, backup, restore и replication должны стать
collection-aware;
- изоляция отказов и ручная диагностика станут слабее, потому что одна
поврежденная физическая область потенциально затрагивает несколько коллекций.
Для множества маленьких коллекций общий набор shard-файлов может быть даже лучше:
меньше fd, меньше директорий, лучше locality, меньше startup overhead. Для
нескольких горячих коллекций текущая физическая изоляция может быть быстрее и
предсказуемее.
Практичные промежуточные варианты:
- уменьшать `shard_count` для маленьких коллекций;
- сделать fd budget и lazy-open для immutable files;
- закрывать cold collections;
- шарить `Engine` только внутри группы коллекций одного backend'а;
- отдельно рассматривать Bitcask и FixedStore, потому что Fixed сейчас имеет
другую модель: один `fixed.data` per shard и in-place writes.
## Вредит ли Linux-серверу много открытых file descriptor?
Сами по себе сотни или тысячи открытых fd на Linux нормальны. Производительность
сервера обычно не падает только из-за того, что у процесса открыто 300, 1000 или
5000 обычных файлов.
I/O latency определяется диском, page/direct I/O, locks, fsync, cache misses,
очередями и contention, а не самим числом открытых fd. Открытый fd в основном
занимает kernel memory и учитывается в лимитах процесса.
Реальные проблемы начинаются, когда:
- процесс упирается в `RLIMIT_NOFILE` и получает `EMFILE` / `Too many open files`;
- системный лимит fd слишком низкий для DB/server процесса;
- код регулярно сканирует все fd или держит слишком много неиспользуемых файлов
открытыми;
- из-за открытых immutable files растет kernel memory и сложность управления
lifecycle'ом файлов.
Для среднего или большого server/DB проекта `ulimit -n 512` скорее низкий лимит.
Нормально выставлять `4096`, `8192`, `65536` через systemd `LimitNOFILE=`,
container limits или service manager.
Но если обычный проект с 20 коллекциями уже требует поднятия лимита, это сигнал,
что дефолтная модель fd стоит пересмотреть. В armdb основной множитель сейчас:
```text
collection_count * shard_count * files_per_shard
```
Поэтому ближайшая практичная оптимизация без большого рефакторинга - дать мелким
коллекциям меньший `shard_count` или сделать lazy-open/reopen для immutable files.