≫ Защита и сжатие таблицы

Структура таблицы в реальном времени

Обычную таблицу можно создать из внешнего источника с помощью специального инструмента под названием indexer, который читает "рецепт" из конфигурации, подключается к источникам данных, извлекает документы и строит файлы таблицы. Это длительный процесс. Если ваши данные изменяются, таблица устаревает, и её нужно перестраивать из обновлённых источников. Если данные изменяются инкрементально, например, в блоге или новостной ленте, где старые документы не меняются, а добавляются только новые, перестройка будет занимать всё больше времени, так как вам придётся снова и снова обрабатывать архивные источники при каждом проходе.

Один из способов решения этой проблемы — использовать несколько таблиц вместо одной большой. Например, можно обработать источники, созданные в предыдущие годы, и сохранить таблицу. Затем взять только источники текущего года и поместить их в отдельную таблицу, перестраивая её так часто, как необходимо. После этого обе таблицы можно объединить в распределённую таблицу и использовать её для запросов. Суть в том, что при каждой перестройке вы обрабатываете данные не старше 12 месяцев, а таблица с более старыми данными остаётся без изменений и не требует перестройки. Можно пойти дальше и разделить таблицу за последние 12 месяцев на месячные, недельные или дневные таблицы и так далее.

Этот подход работает, но вам нужно вручную поддерживать распределённую таблицу. То есть добавлять новые части, удалять старые и следить, чтобы общее количество частичных таблиц не было слишком большим (при слишком большом количестве таблиц поиск может замедлиться, а ОС обычно ограничивает число одновременно открытых файлов). Для решения этой задачи можно вручную объединять несколько таблиц, запуская indexer --merge. Однако это решает только проблему большого количества таблиц, усложняя обслуживание. И даже при переиндексации «по часам» у вас, скорее всего, будет заметный временной разрыв между появлением новых данных в источниках и перестройкой таблицы, которая делает эти данные доступными для поиска.

Таблица в реальном времени создана для решения этой проблемы. Она состоит из двух частей:

  1. Специальной таблицы в оперативной памяти (называемой RAM chunk), которая содержит части данных, поступающих прямо сейчас.
  2. Набора обычных таблиц, называемых disk chunks, которые были построены ранее.

Это очень похоже на стандартную распределённую таблицу, состоящую из нескольких локальных таблиц.

Вам не нужно строить такую таблицу, запуская indexer, который читает "рецепт" из конфигурации и источники данных таблиц. Вместо этого таблица в реальном времени предоставляет возможность «вставлять» новые документы и «заменять» существующие. При выполнении команды 'insert' вы отправляете новые документы на сервер. Он строит небольшую таблицу из добавленных документов и сразу же выводит её в онлайн. Таким образом, сразу после завершения команды 'insert' вы можете выполнять поиск во всех частях таблицы, включая только что добавленные документы.

Сервер поиска автоматически поддерживает таблицу, так что вам не нужно об этом беспокоиться. Однако вам может быть интересно узнать некоторые детали о том, «как она поддерживается».

Во-первых, поскольку индексированные данные хранятся в оперативной памяти — что будет при аварийном отключении питания? Потеряю ли я тогда таблицу? Перед завершением сервер сохраняет новые данные в специальный «binlog». Это один или несколько файлов, находящихся на вашем постоянном хранилище, которые инкрементально растут по мере добавления изменений. Вы можете настроить поведение относительно того, как часто новые запросы (или транзакции) сохраняются в binlog и как часто выполняется команда 'sync' для binlog-файла, чтобы заставить ОС действительно сохранить данные на надёжном носителе. Самый параноидальный подход — сбрасывать и синхронизировать после каждой транзакции. Это самый медленный, но и самый безопасный метод. Самый дешёвый способ — полностью отключить binlog. Это самый быстрый метод, но вы рискуете потерять индексированные данные. Также предусмотрены промежуточные варианты, например, сброс/синхронизация каждую секунду.

Binlog предназначен специально для последовательного сохранения новых транзакций; это не таблица и по нему нельзя выполнять поиск. Это всего лишь страховка, гарантирующая, что сервер не потеряет ваши данные. Если произойдёт внезапный сбой и всё упадёт из-за программной или аппаратной ошибки, сервер загрузит самый свежий доступный дамп RAM chunk и затем воспроизведёт binlog, повторяя сохранённые транзакции. В итоге он достигнет того же состояния, в котором находился в момент последнего изменения.

Во-вторых, как насчёт ограничений? Что если я хочу обработать, скажем, 10 ТБ данных, но они просто не помещаются в оперативную память! Оперативная память для таблицы в реальном времени ограничена и может быть настроена. Когда индексируется определённый объём данных, сервер управляет RAM-частью таблицы, объединяя маленькие транзакции, чтобы их количество и общий размер оставались небольшими. Однако этот процесс иногда может вызывать задержки при вставке. Когда объединение уже не помогает, и новые вставки достигают лимита RAM, сервер преобразует таблицу в оперативной памяти в обычную таблицу на диске (называемую disk chunk). Эта таблица добавляется в набор таблиц второй части RT-таблицы и становится доступной онлайн. Затем RAM очищается, и пространство освобождается.

Когда данные из RAM надёжно сохранены на диск, что происходит:

  • когда сервер сохраняет собранные данные как дисковую таблицу
  • или когда он сбрасывает RAM-часть при корректном завершении работы или с помощью ручного сброса

binlog для этой таблицы больше не нужен. Поэтому он удаляется. Если все таблицы сохранены, binlog будет удалён.

Третье, как насчёт сбора дисков? Если наличие множества частей диска замедляет поиск, в чём разница, если я создаю их вручную в виде распределённой таблицы, или они создаются как части диска (или «чанки») таблицей RT? В обоих случаях вы можете объединить несколько таблиц в одну. Например, можно объединить почасовые таблицы за вчерашний день и вместо этого сохранить одну «суточную» таблицу за вчера. При ручном обслуживании вам нужно самостоятельно продумывать схему и команды. С таблицей RT сервер предоставляет команду OPTIMIZE, которая делает то же самое, но избавляет вас от ненужных внутренних деталей.

Четвёртое, если мой «документ» представляет собой «мини-таблицу» и он мне больше не нужен, я могу просто выбросить его. Но если он «оптимизирован», то есть смешан с множеством других документов, как я могу отменить или удалить его? Да, индексированные документы «смешаны» вместе, и нет простого способа удалить один без перестройки всей таблицы. И если для обычных таблиц перестройка или слияние — это нормальный способ обслуживания, то для таблицы реального времени это сохраняет только простоту манипуляций, но не «реальное время». Чтобы решить эту проблему, Manticore использует хитрость: когда вы удаляете документ, идентифицированный по ID документа, сервер просто отслеживает этот номер. Вместе с другими удалёнными документами их ID сохраняются в так называемом kill-list. При поиске по таблице сервер сначала извлекает все подходящие документы, а затем исключает документы, найденные в kill-list (это самое базовое описание; на самом деле внутри всё сложнее). Суть в том, что ради «немедленного» удаления документы фактически не удаляются, а просто помечаются как «удалённые». Они всё ещё занимают место в различных структурах таблицы, по сути являясь мусором. Статистика слов, которая влияет на ранжирование, также не затрагивается, то есть работает именно так, как заявлено: мы ищем среди всех документов, а затем просто скрываем помеченные как удалённые из итогового результата. Когда документ заменяется, это означает, что он убивается в старых частях таблицы и вставляется заново в самую свежую часть. Все последствия «скрытия через killlist» также действуют в этом случае.

Когда происходит перестройка какой-то части таблицы, например, когда сливаются некоторые транзакции (сегменты) RAM-чанка, или когда RAM-чанк конвертируется в дисковый чанк, или когда два дисковых чанка объединяются, сервер выполняет комплексную итерацию по затронутым частям и физически исключает удалённые документы из всех них. То есть, если они были в списках документов некоторых слов — они вычищаются. Если это было уникальное слово — оно удаляется полностью.

В итоге: удаление работает в два этапа:

  1. Сначала мы помечаем документы как «удалённые» в реальном времени и подавляем их в результатах поиска.
  2. Во время некоторой операции с чанком таблицы RT мы окончательно физически удаляем удалённые документы.

Пятое, если таблица RT содержит обычные дисковые таблицы в своей коллекции, могу ли я просто добавить в неё свою готовую старую дисковую таблицу? Нет. Это невозможно, чтобы избежать ненужной сложности и предотвратить случайное повреждение. Однако, если ваша таблица RT только что создана и не содержит данных, вы можете ATTACH TABLE вашу дисковую таблицу к ней. Ваша старая таблица будет перемещена внутрь таблицы RT и станет её частью.

В итоге о структуре таблицы RT: это умно организованная коллекция обычных дисковых таблиц с быстрой таблицей в памяти, предназначенная для вставок в реальном времени и полуреального времени удаления документов. Таблица RT имеет общую схему, общие настройки и может легко обслуживаться без глубокого погружения в детали.

Last modified: August 28, 2025