所以我已经阅读了所有RMDB与BigTable的争论
我尝试使用BigTable概念建模一个简单的游戏类。
目标:提供非常快速的读取和相当容易的写入
场景:我的用户模型中有500,000个用户实体。我的用户在他/她的游戏页面顶部看到了一个用户统计信息(想想像黑手党战争一样的状态栏),所以无论他/她进入游戏,统计数据都会刷新。
由于频繁调用,为什么我不围绕这个事实对用户进行建模?
代码:
# simple User class for a game
class User(db.Model):
username = db.StringProperty()
total_attack = db.IntegerProperty()
unit_1_amount = db.IntegerProperty()
unit_1_attack = db.IntegerProperty(default=10)
unit_2_amount = db.IntegerProperty()
unit_2_attack = db.IntegerProperty(default=20)
unit_3_amount = db.IntegerProperty()
unit_3_attack = db.IntegerProperty(default=50)
def calculate_total_attack(self):
self.total_attack = self.unit_1_attack * self.unit_1_amount + \
self.unit_2_attack * self.unit_2_amount + \
self.unit_3_attack * self.unit_3_amount + \
这就是我如何接近它(随意评论/批评)
优点:
一切都在一张大桌子上
2.无需使用ReferenceProperty,也无需使用MANY-TO-MANY关系
3.更新非常容易:只需按键名称获取用户实体
4.将查询的实体转移到模板引擎很容易。
缺点:
1.如果我拥有100个具有不同能力(攻击,防御,灵巧,魔法等)的不同单位,那么我将拥有一张非常巨大的桌子。
2.如果我必须更改某个攻击单位的值,那么我将不得不通过所有500,000个用户实体来更改它们中的每一个。 (也许一个cron作业/任务队列会有帮助)
每个实体的大小为5-10 kb(顺便说一下,如果我将它们上传到生产服务器,我如何检查实体的大小?)。
所以我指望App Engine上的磁盘空间很便宜,我需要最小化数据存储API调用的数量。我会尝试将实体记忆一段时间。
从本质上讲,这里的一切都违背了RMDB
很想听听你的想法/想法/经历。
答案 0 :(得分:1)
首先简单回答“我怎么知道一个实体有多大?”:一旦你在应用引擎服务器上的应用中获得了一些数据,你就可以转到你的应用了控制台并单击“数据存储区统计信息”链接。这将为您提供有关您的实体的一些基本统计信息,例如每种类型使用的空间大小,使用最多磁盘空间的属性类型等等。但我认为您不能深入到某个特定用户的级别。
现在这里有一些关于你的设计的想法。为你的单位创建一个单独的表是值得的。即使您最终只有几百个单位,也很容易将它们全部保存在内存中,因此查找每个单元的详细信息可以忽略不计。它会花费你一些额外的API调用,以便在第一次使用单元的信息时初始填充内存缓存,但之后你将不必从数据库中获取每个单元的详细信息,从而节省了大量的CPU周期。 ,当你需要更新一个单元时(你已经意识到它将非常昂贵),并节省大量的API调用。此外,如果每个User对象只需要一个Unit实体的引用而不是持有,它将使用更少的磁盘空间所有细节本身。 (当然这取决于你需要存储的每个单元的信息量,但你确实提到最终你会为每个单元存储大量的统计数据)
如果您有单独的单位表,它还可以让您更灵活地保持用户对象。您可以只获得一个单位参考列表,而不是每个单元都需要特定字段。这样,如果添加单位类型,则无需修改用户类型。
答案 1 :(得分:1)
您应该为您的单位创建独立模型。 “虽然单个实体或实体组对其更新速度有限制,但App Engine擅长处理分布在不同实体上的许多并行请求,我们可以通过使用分片来利用这一点。” Have a look at this article。它可能很有用。
答案 2 :(得分:0)
根据彼得的想法,我提出了以下修订后的用户模型。你们的人怎么想?
class Unit(db.Model):
name = db.StringProperty()
attack = db.IntegerProperty()
#initialize 4 different types of units
Unit(key_name="infantry",name="Infantry",attack=10).put()
Unit(key_name="rocketmen",name="Rocketmen",attack=20).put()
Unit(key_name="grenadiers",name="Grenadiers",attack=30).put()
Unit(key_name="engineers",name="Engineers",attack=40).put()
class User(db.Model):
username = db.StringProperty()
# eg: [10,50,100,200] -> this represents 10 infantry, 50 rocketmen, 100 grenadiers and 200 engineers
unit_list_count = db.ListProperty(item_type=int)
# this holds the list of key names of each unit type: ["infantry","rocketmen","grenadiers","engineers"]
unit_list_type = db.StringListProperty()
# total attack is not calculated inside the model. Instead, I will use a
# controller file ( a py file ) to call the contents of unit_list_count and
# unit_list_type of a certain user entity, and make simple multiplications and additions to get total attack
并且是的,所有unit_types都将被memcached,以便可以检索它们以快速计算总攻击点。
希望听到大家对此的看法。