谷歌AppEngine分片问题

问题描述:

我的背景是关系数据库的,我正在做一些实验,主要用于学习Google AppEngine。我想建立一个“选举”应用程序,用户属于一个州(CA,NY,TX等),他们选择一个党(共和党,*党等),并投票支持某一年该应用可以在2016年重新使用)。谷歌AppEngine分片问题

我希望用户能够看到他们的投票历史,并且可能会在当前选举中更改一次。此外,我将要求用户指定他们的邮政编码,并认为按州和/或邮政编码运行一些报告会很好。

使用关系数据库,看来你会创造一些像这样的表:

Users(userid, username, city, state, zip) 
UserVote(userid, year, vote) 

然后使用SQL来运行报告。使用AppEngine数据存储区看来,运行汇总报告似乎是一项挑战。

我最初的想法是按User分片,其中每个用户可以包含一个Votes的列表,然后可以双重保存其他地方的聚合。

有什么建议吗?

P.S.我见过AppEngine-MapReduce项目,但我不确定这是否会过度。

+0

你是什么意思的'用户分片'?为什么mapreduce过度杀伤? – 2011-05-30 21:53:02

+0

关于'用户分片' - 根据我对数据存储的有限了解,除非存在层次关系,否则无法跨实体加入。仔细挑选“根”实体(即用户)可让您按相关实体进行查询。关于mapreduce的过度杀伤 - 看起来它可能是一种计算聚合的方法,但在我尝试学习的许多其他事物之上增加了一层额外的复杂性。 – dana 2011-05-31 14:46:09

我不记得确切的地方我读了这个,但是GAE中的List属性在达到约200项后变慢。我会建议反对这个赞成用户和投票的外键方法。

聚合是一个挑战,因为没有任何常见的帮助功能,如MAX,SUM,COUNT等。最好的方法是将聚合和计数存储在单独的数据类型中,您可以轻松查询并在用户每次投票时更新。 它在AppEngine中更容易花时间进行写操作,以便稍后可以更快地进行查询。

以下是一个Java对象的一个​​例子:

@PersistenceCapable 
public class User{ 
    @PrimaryKey 
    @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY) 
    private Key key; 
    ... 
} 

@PersistenceCapable 
public class Vote{ 
    @PrimaryKey 
    @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY) 
    private Key key; 

    @Persistent 
    private Key userKey; // References a User 
    ... 
} 

@PersistenceCapable 
public class UserStats{ 
    @PrimaryKey 
    @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY) 
    private Key key; 

    @Persistent 
    private Key userKey; // References a User 
    ... 
} 

此外,传统的分片没有多大意义,在AppEngine上,因为底层数据存储是专门用来处理查询的大型数据集提供方便。例外情况是,如果您有特定的计数器可以经常更改,并且可能有多个用户同时更改它。这是一种与您在MySQL中习惯的不同类型的分片。这里是谷歌关于分片计数器的文章:http://code.google.com/appengine/articles/sharding_counters.html

+0

感谢您的提示!不幸的是,我认为这可能是一个场景,多个用户可以同时更新同一个计数器:((来自同一州的2个用户投票)我认为这可能是值得我去查看mapreduce项目,但我喜欢你的建议,从'Stats'中的'Vote'中分出'User'。 – dana 2011-05-31 14:54:06

+0

你可以将计数器分割。例如,请参阅http://code.google.com/p/google-app - 发动机采样/源/浏览/中继/分片的计数器/ generalcounter.py – 2011-08-04 04:34:17