Стратегия для произвольных предикатных запросов в Couchdb - PullRequest
3 голосов
/ 24 января 2011

У нас есть приложение, которое может получить огромную пользу от использования хранилища данных на основе документов, такого как CouchDB. Но у нас есть вариант использования запроса, который я пытаюсь реализовать с помощью Map Reduce.

Наши документы действительно содержат только два типа данных:

  1. Числовые атрибуты
  2. Булевы атрибуты

Логические атрибуты, по сути, помечают документ как принадлежащий одному или нескольким неисключительным наборам. Числовые атрибуты всегда нужно только суммировать. Один из способов структурирования документа выглядит следующим образом:

{
  "id": 3123123,
  "attr": {"x": 2, "y": 4, "z": 6},
  "sets": ["A", "B", "C"]
}

С этой структурой легко вычислить совокупные значения x, y, z для множеств A, B и C, но это становится более сложным, когда вы хотите увидеть агрегаты для пересечений, таких как A & C.

В этом небольшом случае я мог выдавать ключи для всех перестановок ABC («A, B, C, AB, AC, BC, ABC»), но меня беспокоит, как это будет масштабироваться. Наши документы могут принадлежать к некоторой комбинации из 80 комплектов, и для них предусмотрен пользовательский интерфейс, который может создать любую их возможную комбинацию.

Я склонен думать, что это не работа для CouchDB, и, возможно, MongoDB или что-то еще лучше подойдет для этой проблемы.

Я что-то упустил?

1 Ответ

3 голосов
/ 24 января 2011

Структура данных, которая может эффективно вычислять и кэшировать все эти значения, будет довольно сложной. Я не уверен, что любая система баз данных может сделать это без перебора подмножеств. Пересечение - общеизвестно сложная операция, и CouchDB на самом деле не имеет ничего доступного для правильной обработки пересечения.

Как вы правильно определили, испускание всех перестановок ( подмножеств , если быть точным) станет бременем памяти, поскольку все равно будет умножать ваши предметы на огромный коэффициент (2 n *). 1006 * пар ключ-значение для n наборов). Вы можете уменьшить это, сложив префиксы вместе (структура ключа CouchDB позволяет вам извлекать значения для ["A"] и ["A","B"], когда вы излучаете для ["A","B","C"], используя опцию уровня группы), но только в 2 раза (2 n-1 пар ключ-значение для n наборов).

Итак, если у ваших предметов есть в среднем три связанных набора, у вас все будет хорошо (4 пары ключ-значение вместо 3), но четыре связанных набора тяжелее (8 вместо 4), а пять начинает раздражает (16 вместо 5). Это также делает элементы со многими связанными наборами уязвимыми для проблем с производительностью (элемент из 10 наборов может создать более 500 пар ключ-значение).

Подход среднего уровня мог бы состоять в том, чтобы выдавать ключи длиной до четырех наборов (это просто удваивает требуемую память) и запускать некоторую обработку на стороне приложения, когда требуется более глубокое пересечение (захватывать все элементы без сокращения, запускать сокращение в приложении). Если повезет, количество соответствующих предметов будет меньше - если это не так, вы всегда можете использовать максимальный размер набора, чтобы пожертвовать большим объемом памяти для большей производительности.

Противоположным подходом было бы иметь обновление приложения 2 n итогов, когда каждый документ вставляется / обновляется (путем извлечения всех «итоговых» документов, которые соответствуют подмножеству текущего элемента). Эти итоги будут храниться в другой базе данных и будут запрашиваться по ключу. Этот подход лучше, если вы можете позволить себе обновлять итоги на лету (или ваша архитектура позволяет обновлять их, прослушивая обновления в основной базе данных), поскольку это делает запросы молниеносными.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...