
# Индексы

Индексы `DocStore` хранятся рядом с коллекцией в `.storh/indexes`. Это обычные файлы, полностью производные от записей, которые можно перестроить в любой момент. Объявите их с помощью цепочки вызовов или через [схему](https://storh.inline0.dev/ru/docs/schema):

```php
$docs->indexes()
    ->field('slug')->unique()
    ->field('kind')
    ->field('publishedAt')->range()
    ->sync();
```

Типы индексов:

- индексы равенства для таких полей, как `kind` или `status`: отдельный файл для каждого уникального значения, поэтому при точечном поиске читается только файл с нужным значением
- уникальные индексы для таких полей, как `slug`: уникальность проверяется при записи, а повторное значение приводит к ошибке `put()` до начала записи
- индексы диапазонов для скалярных значений: отсортированный файл с разреженными контрольными точками для быстрого поиска; поддерживают `gt`, `gte`, `lt`, `lte`, `between` и `prefix`

Индексы диапазонов также могут выполнять `orderBy` по тому же полю с помощью `limit` непосредственно в порядке индекса — по возрастанию или убыванию, без загрузки и сортировки всего результата.

Если запрос объединяет два условия `eq` по полям с индексами равенства без ограничений уникальности, storh может использовать автоматически созданную составную корзину для этой пары полей. Это ускоряет выборочную фильтрацию по двум полям без необходимости объявлять еще один индекс.

## Согласованность и восстановление

Записи индексов обновляются после атомарной замены файла записи, под блокировкой записи коллекции, поэтому данные и индексы изменяются согласованно. `verify()` сравнивает каждый индекс с полным сканированием записей и сообщает о расхождениях; `reindex()` перестраивает все настроенные индексы по файлам записей; `repair()` помещает поврежденные записи в карантин, а затем перестраивает индексы.

```php
$docs->reindex();

$plan = $docs
    ->query()
    ->where('slug')->eq('home')
    ->explain();
```

`explain()` возвращает `index_scan`, когда планировщик может использовать настроенный индекс, и `full_scan` в противном случае.
