В этой статье мы говорим о новых опциях для загрузки данных, введенных в 3.0.2
Индекс с данными состоит из нескольких компонентов, таких как словарь, документы и списки попаданий, атрибуты. Весь индекс не загружается полностью в ОЗУ, так как он может не поместиться, вместо этого его компоненты читаются и загружаются различными способами.
Атрибуты
Атрибуты по умолчанию загружаются в ОЗУ, но было возможно выбрать, загружать ли их все, загружать только скалярные типы (целые числа или числа с плавающей запятой) или оставлять их на диске.
Атрибуты загружаются как файлы с отображением в памяти. Преимущество загрузки атрибутов с использованием mmap() заключается в лучшей производительности по сравнению с классическим методом seek&read с использованием pread(). Это также позволяет использовать большие файлы с небольшими объемами ОЗУ.
В 2.x загрузка атрибутов обрабатывалась через ondisk_attrs. Даже когда мы выбираем загрузку атрибутов в ОЗУ, чтение всего файла с помощью mmap() не гарантирует, что страницы файла останутся в ОЗУ, так как ядро ОС может освободить их (это не проблема для приложения, так как файлы с отображением в памяти поддерживаются самим файлом на диске). Чтобы быть уверенным, что атрибуты остаются в ОЗУ и ОС не выгружает их на диск, необходимо использовать mlock.
В 3.0.2 мы решили внести изменения и вместо того, чтобы иметь настройку для типов атрибутов, которые нужно загружать, и одну для mlocking, сделать две настройки, каждая для типов атрибутов, которые определяют, как они загружаются и должны ли они быть заблокированы.
Новые настройки -
access_blob_attrs
- которые управляют атрибутами переменной длины (строка, JSON, MVA) -
и access_plain_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), если, например, у вас недостаточно ОЗУ для всех, и ваши запросы выполняют больше операций (фильтрация, группировка, сортировка) над атрибутами переменной длины.
Также возможно делать mlocking только некоторых атрибутов. Например, мы хотим, чтобы числовые атрибуты оставались в ОЗУ, но другие атрибуты мы можем предварительно загрузить в ОЗУ, но согласны не блокировать их, чтобы освободить немного места в памяти.
Полнотекстовый индекс
Часть полнотекстового индекса включает в себя несколько компонентов. Компонент словаря (.spi) всегда загружается в ОЗУ, так как он критически важен для производительности полнотекстового поиска, и его размер не велик. Списки документов (.spd) содержат ссылки индексированных слов на документы и поля. Этот компонент обычно большой, и к нему обращались до этого с помощью pread().
Другим компонентом полнотекстового индекса являются списки попаданий (.spp), которые содержат позиции слов в полях. Списки попаданий также могут быть большими (но не такими большими, как списки документов) и к ним обращались так же, как и к спискам документов. Начиная с 3.0.2 оба компонента могут быть загружены с помощью mmap() вместо pread(), используя
access_doclists
и access_hitlists. Настройка принимает два значения: file (который использует pread() и является значением по умолчанию) и mmap.
Как установить директивы памяти?
По умолчанию используется файл для компонентов полнотекстового индекса и mmap_preread для всех атрибутов, что является наиболее сбалансированным профилем между использованием памяти и производительностью поиска.
Чтобы убедиться, что данные атрибутов, загруженные в память, не будут сброшены ОС, можно использовать mlock. Блокировка должна быть на системах, где достаточно памяти для размещения атрибутов, но также оставлять достаточно памяти для списков документов/попаданий. Лучшая производительность достигается, когда индексы могут быть полностью загружены/кэшированы в ОЗУ. Списки документов/попаданий, использующие метод файла, могут быть разогреты, отправив их файлы в /dev/null.
В случаях, когда необходимо получить наилучшую производительность с первого запроса, можно использовать опцию --force-preread у searchd. Эта опция должна использоваться с осторожностью, так как демон не отвечает на входящие запросы, пока не завершится запуск. Для одиночных установок это означает, что поисковые запросы невозможны, что может быть неприемлемо в зависимости от времени, необходимого для завершения запуска по сравнению с ответами в это время с большими временными затратами.
Если индексы больше доступной памяти или приемлемо иметь более длительное время разогрева, следует использовать простой file/mmap. Если индексы не помещаются хорошо в ОЗУ, производительность будет зависеть от производительности хранилища. Выбор между большим объемом памяти и более быстрым хранилищем зависит от стоимости каждого. Более быстрое хранилище (например, NVMe) уменьшит недостатки недостатка памяти. Наличие достаточного объема памяти, но медленного хранилища означает, что старты или перезагрузки индексов будут медленнее, и производительность пострадает, пока индексы не будут загружены в память.