
# 索引

`DocStore` 索引存储在集合旁边的 `.storh/indexes` 下。
它们是普通文件，完全根据记录派生，并且可以随时重建。可以通过流式方式或借助
[架构](https://storh.inline0.dev/zh/docs/schema)声明索引：

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

索引类型：

- 用于 `kind` 或 `status` 等字段的相等索引：每个不同值对应一个文件，因此点查只需读取匹配值的文件
- 用于 `slug` 等字段的唯一索引：在写入时强制执行，重复值会在写入任何内容之前触发 `put()` 失败
- 用于标量值的范围索引：带有稀疏查找检查点的排序文件，可处理 `gt`、`gte`、`lt`、`lte`、`between` 和 `prefix`

范围索引还可以直接根据索引顺序，通过 `limit` 回答同一字段上的 `orderBy`，支持升序或降序，无需将整个结果载入内存再排序。

当查询组合两个非唯一、带相等索引字段上的 `eq` 谓词时，storh 可以为这对字段使用自动复合分桶。无需声明其他索引，即可让有选择性的双字段筛选保持快速。

## 一致性与修复

记录文件原子替换后，会在集合写锁下更新索引条目，使记录和索引同步变更。`verify()` 会将每个索引与完整记录扫描结果进行比较并报告偏差；`reindex()` 会根据记录文件重建所有已配置的索引；`repair()` 会隔离损坏记录，然后重建索引。

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

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

当规划器可以使用已配置索引时，`explain()` 会返回 `index_scan`，否则返回 `full_scan`。
