Как избежать взрыва индексов и ограничений на скорость записи в группе объектов с помощью appengine - PullRequest
3 голосов
/ 02 марта 2011

У меня есть приложение, в котором есть Course s, Topic s и Tag s.Каждый Topic может иметь множество Course с и иметь Tag с.Я хочу посмотреть каждый Topic, который имеет определенный Tag x и имеет определенный Course y.

  1. Наивно, я даю каждому стандарту список Courseидентификаторы и Tag идентификаторы, так что я могу select * from Topic where tagIds = x && courseIds = y.Я думаю, что этот запрос потребовал бы взрывающегося индекса: с 30 курсами и 30 тегами мы рассматриваем ~ 900 записей индекса, верно?При 50 х 20 я нахожусь за пределом в 5000 входов.

  2. Я мог бы просто select * from Topic where tagIds = x, а затем использовать цикл for, чтобы просмотреть результат, выбрав только Topic чьи courseIds.contain(y).Это возвращает гораздо больше результатов, чем мне интересно, и тратит много времени на десериализацию этих результатов, но индекс остается небольшим.

  3. Я мог бы select __KEY__ from Topic where tagIds = x И select __KEY__ from Topic where courseIds = y и найтипересечение в моем коде приложения.Если наборы малы, это может быть неоправданно.

  4. Я мог бы создать своего рода таблицу соединений, TopicTagLookup с полями tagId и courseId.Родительский ключ этих объектов будет указывать на соответствующий Topic.Тогда мне нужно было бы сделать одну из этих TopicTagLookup сущностей для каждой комбинации courseId x tagId x соответствующий идентификатор темы.Это фактически похоже на создание моего собственного индекса.Это все еще взорвалось бы, но не было бы никакого предела в 5000 входов.Однако теперь мне нужно записать 5000 сущностей в одну и ту же группу сущностей, что будет соответствовать пределу скорости записи в группе сущностей!

  5. Я мог бы предварительно рассчитать каждый запрос.Объект TopicTagQueryCache будет содержать tagId, courseId и List<TopicId>.Тогда запрос выглядит как select * from TopicTagQueryCache where tagId=x && courseId = y, получая список идентификаторов тем, а затем используя getAllById вызов в списке.Аналогично # 3, но у меня есть только одна сущность для каждого CourseId x tagId.Нет необходимости в группах сущностей, но теперь у меня есть этот потенциально огромный список для ведения транзакций.

Appengine отлично подходит для запросов, которые можно предварительно рассчитать.Я просто не вижу способа эффективно рассчитать этот запрос.Вопрос сводится к следующему:

Каков наилучший способ упорядочить данные, чтобы мы могли выполнять операции над множествами, например, нахождение Topic s на пересечении Course и Tag

Ответы [ 3 ]

2 голосов
/ 03 марта 2011

Ваша оценка ваших вариантов верна. Если вам не нужны никакие критерии сортировки, вариант 3 уже более или менее уже сделан для вас хранилищем данных App Engine со стратегией объединения слиянием. Просто выполните запрос, как описано в опции 1, без каких-либо фильтров сортировки или неравенства, и App Engine выполнит внутреннее объединение в хранилище данных и выдаст только соответствующие результаты.

Параметры 4 и 5 аналогичны шаблону индекса отношений, задокументированному в этого доклада .

1 голос
/ 02 марта 2011

Мне нравится # 5 - вы по сути создаете свой собственный (взрывающийся) индекс. Это будет быстрый запрос.

Единственным недостатком является то, что вы должны поддерживать его вручную (следующий абзац), а для извлечения сущности Topic потребуется дополнительный запрос (сначала вы запрашиваете TopicTagQueryCache, чтобы получить идентификатор темы, а затем вам нужно фактически получить в тему).

Обновление предложенного вами TopicTagQueryCache также не должно быть проблемой. Я не стал бы беспокоиться о том, чтобы сделать это транзакционно - этот «индекс» просто устареет в течение короткого периода времени, когда вы обновите Topic (в худшем случае ваш Topic будет временно отображаться в результатах, которые он больше не должен показывать и, возможно, потребуется некоторое время, прежде чем он появится в новых результатах, которые он должен показать это - это не так уж плохо). Вы даже можете сделать это обновление в очереди задач (чтобы убедиться, что это потенциально большое количество записей в базу данных выполнено успешно, и чтобы вы могли быстро завершить запрос, чтобы ваш пользователь не ждал).

0 голосов
/ 03 марта 2011

Как вы сказали сами, вы должны упорядочить данные, чтобы облегчить масштабирование своего приложения, таким образом, вопрос Каков наилучший способ упорядочить данные, чтобы мы могли выполнять операции над наборами, такие как поиск тем в пересечении курс и тег?

Вы можете хранить свои собственные индексы этих наборов, создавая объекты CourseRef и TopicRef, которые состоят только из Key, причем часть ID является фактическим ключом соответствующей сущности. Эти объекты «Ref» будут находиться под определенным тегом, поэтому фактические ключи не дублируются. Итак, структура для данного тега: Tag \ CourseRef ... \ TopicRef ...

Таким образом, используя тег и курс, вы создаете Key Tag \ CourseRef и делаете запрос предка , который дает вам набор ключей, которые вы можете получить. Это очень быстро, так как на самом деле это прямой доступ, и он должен обрабатывать большие списки курсов или тем без проблем со свойствами списков.

Этот метод потребует от вас использования API хранилища данных в некоторой степени. Как вы можете видеть, это дает ответ на конкретный вопрос, и модель не принесет пользы для других типов операций Set.

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