В этой статье мы обсудим, как работают убойные списки в Manticore Search 3.
Обычные индексы неизменяемы в плане добавления новых документов: после создания невозможно добавить больше данных, можно только обновлять атрибуты существующих документов. Чтобы держать индекс в соответствии с первичными данными (которые могут быть в базе данных или файлах), индекс необходимо обновить, выполнив полную переиндексацию. Эта операция может занять время. В некоторых случаях полная переиндексация может занять часы или даже больше.
Это означает, что данные для поиска могут отставать от оригинального хранения данных, и последний контент имеет время ожидания до тех пор, пока индекс не будет переиндексирован. Чтобы исправить это, была введена концепция дельта-индекса. Дельта - это индекс с той же структурой, что и более крупный (так называемый ‘основной’) индекс, но он предназначен для захвата документов, которые были добавлены в базу данных после создания основного индекса. Точка захвата обычно является идентификатором документа или временной меткой.
В то время как дельта захватывает новые документы (которые никогда не существовали), в большинстве случаев также необходимо захватывать измененные документы. Еще одним распространенным требованием является возможность каким-то образом игнорировать документы, которые были удалены. Измененные документы могут быть включены в дельту, но они представляют собой проблему: поиск как в основном, так и в дельта индексах приведет к двум версиям одного и того же документа - старой в основном и новой в дельте - и движок не знает, какую из них выбрать.
Чтобы преодолеть эти проблемы, была добавлена новая концепция: убойный список - список идентификаторов документов в дельта индексе, которые известны как измененные или удаленные, чтобы индекс игнорировал их при выполнении поиска в основном индексе.
Пока все хорошо. Однако в версии 2 движок должен был применять убойный список к набору результатов, извлеченных из основного индекса, перед объединением с набором результатов из дельты для предоставления окончательного результата. В целом это работало хорошо для многих пользователей, но применение убойных списков к каждому запросу действительно сказывалось на производительности. Это не так заметно на маленьких индексах или маленьких убойных списках, но начинает проявляться на больших индексах, которые “занимают целую вечность” для переиндексации, для которых дельта индексы могут привести к большим наборам убойных списков.
<img src="killlists-v2-optimized.webp" alt="img"> Убойные списки в 2.x
Manticore 3 ввел значительные изменения, произведя масштабное обновление движка хранения индексов. Убойные списки также нуждались в изменении.
Это было вызвано двумя причинами: существующий способ убойных списков оказался проблематичным в некоторых крайних случаях, и он также не подходил для нового движка хранения.
Поэтому вместо того, чтобы применять убойные списки каждый раз, когда выполняется запрос, почему бы не сделать это один раз? В версии 3 в источниках дельта индекса мы по-прежнему определяем источник для убойных списков (sql_query_killlist), но в конфигурации индекса нам нужно определить цели убойных списков.
Когда индексы загружаются, движок проверяет, есть ли для индекса убойный список, который нужно применить. Если один (или несколько) найдены, он применяет этот убойный список к индексу, помечая совпадающие документы как удаленные. Когда запрос выполняется над индексом, эти помеченные документы просто игнорируются (как будто их не существует). Поскольку это подавление уже выполнено при запуске или ротации индекса, наличие дельты не требуется, чтобы удаленные документы больше не появлялись в результатах.
<img src="killlists-v3-optimized.webp" alt="img"> Цели убойных списков определяются в killlist_target директиве индекса. Директива ожидает список индексов и режим примененных убойных списков. В настоящее время поддерживаются 3 режима:
kl - идентификаторы документов из определенного убойного списка (по sql_query_killlist) будут использоваться для подавления
id - вместо этого используются идентификаторы документов из индекса (и любой определенный sql_query_killlist будет проигнорирован)
или по умолчанию, если вы не укажете ‘kl’ или ‘id’, будут использоваться как идентификаторы документов из индекса, так и sql_query_killlist
Пример
index delta {
...
killlist_target = index_one:kl, index_two:id
...
}
Директиву цели можно изменить с помощью команды ALTER TABLE, но для применения целевые индексы должны быть перезагружены. Также ALTER не может “отключить” уже удаленные идентификаторы на целевом индексе (извлекая индекс из списка целей).