# New options for loading indexes

В этой статье мы рассказываем о новых опциях загрузки данных, представленных в версии 3.0.2

Индекс с данными состоит из нескольких компонентов, таких как словарь, документы и списки хитов, атрибуты. Весь индекс не загружается полностью в ОЗУ, поскольку может не поместиться, вместо этого его компоненты читаются и загружаются разными способами.

### Атрибуты

По умолчанию атрибуты загружаются в ОЗУ, но была возможность выбирать, загружать их все, загружать только скалярные типы (целые или числа с плавающей точкой) или оставлять их на диске.

Атрибуты загружаются как файлы с отображением в память. Преимущество загрузки атрибутов с помощью `mmap()` — лучшая производительность по сравнению с классическим seek&read с использованием `pread()`. Это также позволяет работать с большими файлами, используя небольшие объёмы ОЗУ.

В версии 2.x загрузка атрибутов осуществлялась через `ondisk_attrs`. Даже если мы выбираем загрузку атрибутов в ОЗУ, чтение всего файла с помощью `mmap()` не гарантирует, что страницы файла останутся в ОЗУ, так как ядро ОС может их освободить (это не проблема для приложения, поскольку mmap‑файлы поддерживаются самим файлом на диске). Чтобы убедиться, что атрибуты остаются в ОЗУ и ОС не выгружает их на диск, необходимо использовать `mlock`.

В версии 3.0.2 мы решили внести изменение и вместо наличия отдельного параметра для типов загружаемых атрибутов и параметра для mlock использовать два параметра, каждый из которых определяет типы атрибутов, способ их загрузки и необходимость блокировки.

Новые настройки — [access_blob_attrs](https://docs.manticoresearch.com/latest/html/conf_options_reference/index_configuration_options.html#access-blob-attrs) — управляет переменной длиной атрибутов (string, JSON, MVA) — и [access_plain_attrs](https://docs.manticoresearch.com/latest/html/conf_options_reference/index_configuration_options.html#access-blob-attrs) — управляет атрибутами фиксированной длины (uint, bigint, float, timestamp, bool). Возможные значения: `mmap`, `mmap_preread` и `mlock`.

Переход от старых директив к новым довольно прост:

* `ondisk_attrs = 0` означает, что ни один атрибут не оставлен на диске и они предварительно читаются в ОЗУ. Это было значение по умолчанию вместе с mlock=0. Сейчас это эквивалентно `access_blob_attrs = mmap_preread` и `access_plain_attrs= mmap_preread`. Этот режим следует использовать, когда все атрибуты могут поместиться в ОЗУ. Чтобы убедиться, что они не выгружаются на диск, можно вместо этого использовать `access_blog_attrs = mlock` и `access_plain_attrs = mlock`, что эквивалентно `ondisk_attrs=0` и `mlock=1`.
* `ondisk_attrs=1` означает, что все атрибуты оставлены на диске. С новыми опциями необходимо указать `access_blob_attrs=mmap` и `access_plain_attrs=mmap`.
* `ondisk_attrs=pool` означает оставлять строки, JSON и MVA‑атрибуты на диске. Чтобы получить тот же эффект сейчас, нужно задать `access_blob_attrs=mmap` и `access_plain_attrs=mmap_preread`.

Но теперь также возможно оставлять числовые атрибуты на диске и загружать вместо них переменной длины (делая `access_blob_attrs=mmap_preread`/`access_plain_attrs=mmap`), если, например, у вас недостаточно ОЗУ для всех атрибутов, а ваши запросы выполняют больше операций (фильтрация, группировка, сортировка) над переменной длиной.

Также возможно выполнять mlock только для некоторых атрибутов. Например, мы хотим, чтобы числовые атрибуты гарантированно оставались в ОЗУ, а остальные атрибуты можно предварительно читать в ОЗУ, но не блокировать их, чтобы освободить часть памяти.


### Полнотекстовый индекс

Полнотекстовая часть индекса сама по себе включает несколько компонентов. Компонент словаря (**.spi**) всегда загружается в ОЗУ, поскольку он критичен для производительности полнотекстового поиска и его размер небольшой. Списки документов (**.spd**) содержат ссылки индексированных слов на документы и поля. Этот компонент обычно большой и до этого доступа осуществлялись с помощью **pread()**.

Другим компонентом полнотекстового индекса являются списки хитов (`.spp`), которые содержат позиции слов в полях. Списки хитов также могут быть большими (но не так большими, как списки документов) и до этого доступ к ним осуществлялся так же, как к спискам документов. Начиная с версии 3.0.2 оба компонента могут загружаться с помощью `mmap()` вместо `pread()`, используя[ access_doclists](https://docs.manticoresearch.com/latest/html/conf_options_reference/index_configuration_options.html#access-doclists) и `access_hitlists`. Параметр принимает два значения: `file `(который использует `pread()` и является значением по умолчанию) и `mmap`.


### Как задать директивы памяти?

По умолчанию для компонентов полнотекстового индекса используется `file`, а для всех атрибутов — `mmap_preread`, что представляет собой наиболее сбалансированный профиль между использованием памяти и производительностью поиска.

Чтобы убедиться, что данные атрибутов, загруженные в память, не будут выгружены ОС, можно использовать `mlock`. Блокировка должна применяться на системах, где достаточно памяти для размещения атрибутов, но при этом остаётся достаточно памяти для списков документов/хитов. Наилучшая производительность достигается, когда индексы могут быть полностью загружены/кешированы в ОЗУ. Списки документов/хитов, использующие метод `file`, можно прогреть, отправив их файлы в /dev/null.

В случаях, когда требуется максимальная производительность уже с первого запроса, можно использовать опцию `--force-preread` демона **searchd**. Эта опция должна использоваться с осторожностью, поскольку демон не отвечает на входящие запросы, пока не завершится запуск. Для одиночных установок это означает, что поисковые запросы невозможны, что может быть неприемлемо в зависимости от времени, необходимого для завершения запуска, по сравнению с более длительным временем отклика в этот период.

Если индексы больше доступной памяти или приемлемо более длительное время прогрева, следует использовать простой `file`/`mmap`. Если индексы не помещаются в ОЗУ, производительность будет зависеть от скорости хранилища. Выбор между большим объёмом памяти и более быстрым хранилищем зависит от их стоимости. Более быстрое хранилище (например, NVMe) уменьшит недостаток недостатка памяти. Наличие достаточного объёма памяти, но медленного хранилища приводит к более медленному запуску или перезагрузке индексов, и производительность будет страдать, пока индексы не загрузятся в память.
