Оптимизация потребления оперативной памяти

Reindexer хранит все данные, мету и индексы в RAM, поэтому он не имеет опции, позволяющей явно ограничить объём потребляемой оперативной памяти. Однако общее потребление памяти можно регулировать косвенно.

Dense-индексы

Флаг dense у индексов сокращает потребление памяти за счёт отключения колоночной оптимизации. Dense-индексы имеют менее эффективные компараторы, но зато не аллоцируют дополнительную память для хранения непрерывного массива ID. В случае полнотекстовых индексов опция dense отключает многопоточное построение индекса и не влияет на потребляемую память.

Фоновая оптимизация индексов

Reindexer создаёт дополнительные маппинги для unordered и ordered индексов в фоновом потоке. Эти маппинги используются для оптимизации сортировок в запросах, в которых используются одновременно tree и hash индексы.

Например:

SELECT * from ns WHERE hash1 = 12345 AND hash2 = 5678 ORDER BY tree

В запросе выше без дополнительных маппингов планировщику приходится выбирать: либо использовать более эффективные индексы hash1 и hash2 для выборки, а затем выполнить сортировку полученных результатов, либо выбрать в качестве основного индекса tree, а условия для hash1/hash2 проверить через компараторы. В случае, если фоновая сортировка индексов завершена, reindexer сможет использовать hash1/hash2 в качестве основных индексов, а затем, используя вспомогательные маппинги выполнить сортировку за O(N) без применения общего алгоритма сортировки.

Для отключения фоновой оптимизации индексов можно установить опцию optimization_timeout_ms в config-неймспейсе в значение 0.

Сброс данных на диск

Непосредственно в момент записи в Reindexer новые данные в сериализованном виде складываются в промежуточные буферы. Эти буферы в большинстве случаев асинхронно записываются на диск в фоновом потоке с периодом 100-200 мс (в некоторых случаях запись происходит синхронно). Опция sync_storage_flush_limit в config-неймспейсе позволяет ограничить максимальное число записей, помещаемых в промежуточный буфер для каждого неймспейса. При превышении этого лимита сброс буфера на диск будет происходить синхронно. Ограничение не распространяется на транзакции, update и delete запросы (их Reindexer старается сбрасывать на диск единым батчем в любом случае).

Конфигурирование размеров индексных кэшей

В Reindexer каждый индекс имеет свой индивидуальный независимый LRU-кэш для выборок. По умолчанию размер этого кэша 128 Мб на индекс. Сконфигурировать его можно через объект cache в config-неймспейсе.

Атомарные копирующие транзакции

Reindexer в некоторых случаях может использовать копирование неймспейса при выполнении транзакции. Этот механизм нужен для того, чтобы избежать долгой эксклюзивной блокировки - вместо этого транзакция применяет к копии неймспейса, и затем происходит атомарная подмена указателя. Такое копирование может приводить к значительному росту потребления RAM в момент коммита транзакции (особенно, если целевой неймспейс занимает много памяти). Доступные стратегии коммита описаны в соответствующем разделе

Кэши аллокаторов

Пользовательские аллокаторы (в частности tcmalloc) могут иметь достаточно агрессивную политику кэширования, приводящую к тому, что значительный объём памяти, помеченный приложением как “свободная” фактически не возвращается в систему, оставаясь в кэше аллокатора. Reindexer позволяет явно управлять размером таких кэшей при помощи опций allocator_cache_limit и allocator_cache_part (более детальное описание этих опций приведено в разделе конфигурации сервера.

Конфигурирование WAL

Write ahead log в reindexer является виртуальным и хранится в памяти в виде циклического буфера ограниченного размера (по умолчанию до 4000000 записей для каждого неймспейса кроме системных). Этот WAL используется только для репликации, чтобы follower мог получить историю изменений с leader’a. Если текущий инстанс не участвует в репликации или является исключительно follower’ом (то есть сам никуда не реплицирует), то wal_size в config-неймспейсе можно задать равным 1, чтобы не хранить лишние данные в RAM. Точно также можно задать меньший размер WAL для отдельных неймспейсов, если текущий инстанс их никуда не реплицирует.