Appengine: нужна помощь в разработке моих сущностей, чтобы они были более масштабируемыми и недорогими - PullRequest
0 голосов
/ 18 декабря 2011

Например, рассмотрите это как сайт онлайн-опроса.

Сущности

Survey (created with questions, answers)

Respondent (кто принимает участие в опросах в параллельно . огромный в №)

  • survey id
  • List (question id, answer id)

Проблема:

Необходимо получить сводку ответов, т. Е. Для любого конкретного survey, для любого question, нет. респондентов, которые выбрали ответ 1 против 2 против 3 (скажем) Сводка должна быть получена дешево, то есть с меньшим количеством звонков, насколько это возможно

Этот код просто , чтобы помочь вам лучше понять:

Survey sampleSurvey = ..
// get all respondents of above survey
List<Respondent> r = getAllRespondents(sampleSurvey);
// update summary per chosen question, answer
for each respondent:
    List<QuestionAnswer> qa = respondent.getChosenAnswers()
    for each chosen question, answer:
          // increments corresponding answer count by 1
          sampleSurvey.updateSummary(question.getId(), answer.getId()) 
// summary update done

// process summary
Summary summary = sampleSurvey.getSummary();
for each available question, answer:
    print 'No. of respondents who chose answer %s for question %s are %s' % (answer.text(), question.text(), answer.count())

Мои мысли :

а. Создание сводной сущности для каждого опроса по мере того, как респондент принимает участие в опросе, обновляя счетчики в сводке entity(Q1 -> A1 -> 4, Q1 -> A2 -> 222,...).

Плюсы: получить сводку, прочитав всего 1 сущность; дешево

Минусы: так как огромных нет. респонденты проводят одно и то же исследование параллельно, это означает, что разногласия между хранилищами данных; осколок решения? нет. из осколков, чтобы быть динамическим в зависимости от нет. респондентов для опросов.

б. Запрашиваем счет против индексов. С моим небольшим знанием об индексации appengine, я не знаю как будет сформирован индекс для вышеуказанной сущности респондента и насколько он будет большим. Также беспокоюсь о нет. из этих дополнительных записей, необходимых для индексов, может произойти взрыв индекса? запрос должен быть что-то вроде
select count(*) from Respondent where surveyId=xx and questId=yy and ansId=zz

Есть ли другие лучшие решения? А что на счет выше? какой из них вы рекомендуете и почему. Большое спасибо за поиск и ваши предложения. Пинг если что то неясно.

Ответы [ 2 ]

1 голос
/ 19 декабря 2011

Обновление резюме с каждой записью нецелесообразно, так как вы быстро столкнетесь с проблемами спора; динамический подсчет результатов будет крайне неэффективным. В этом случае вам лучше вычислять агрегаты, используя пакетный процесс, такой как mapreduce - просто напишите задачу, которая просматривает все ответы на опрос и накапливает соответствующую статистику, и периодически запускайте эту задачу.

1 голос
/ 18 декабря 2011

Я думаю, что это зависит от двух основных факторов:

  1. Знаете ли вы запросы, которые вы хотите выполнить раньше времени?(то есть, когда респонденты отвечают, а не разбивают данные позже.)
  2. Сколько респондентов вы ожидаете?(И #, и скорость.)

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

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

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

...