作为例如将其视为在线调查网站。
实体:
Survey (created with questions, answers)
Respondent
(在并行。巨大的中进行调查。
survey id
List
(question id
,answer id
)问题:
需要获取响应摘要,例如任何特定survey
,任何question
,否。选择答案1 vs 2 vs 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
还有其他更好的解决方案吗?那么上面呢?你推荐哪一个以及为什么。非常感谢您的期待和建议。如果有什么不清楚的话。
答案 0 :(得分:1)
我认为这取决于两个主要因素:
如果您事先不知道查询,那么我认为您可以做的最好的事情就是获取所有实体并计算您需要的信息。 (然后将其缓存在另一个实体或内存缓存中或两者中。)如果你有很多受访者,你可能需要在backend或通过task queue进行此计算以避免命中请求超时/配额。如果您拥有真正庞大的数据量,您甚至可以考虑Mapreduce,这是目前的实验性和仅限Python。
如果您提前知道了这些查询,那么我认为您对单个实体的处理方法是正确的。如果您希望每秒写入超过一次,则可以使用标准sharded counter technique来减少争用。如果您不期望更多,则可以使用单个实体组。
如果您只希望每秒写入一次,可能出现高峰,则另一种选择是使用单个实体,但在任务队列中使用任务来异步更新其计数器;您可以限制任务队列速率以减少争用,只要您不会比完成任务更快地创建任务。这可能更容易编写,特别是如果你有很多要计算的统计数据,尽管我认为上面的分片计数器技术最终可以扩展。
答案 1 :(得分:1)
每次写入都更新摘要是不切实际的,因为您很快就会遇到争用问题;动态计算结果将是非常低效的。在这种情况下,您最好使用批处理(例如mapreduce)计算聚合 - 只需编写扫描所有调查答案的任务并累积相关统计信息,并定期运行此任务。