下面的代码作为一个cronjob定期运行,结果计算成本非常高!主要问题在于for循环,我认为使用更好的过滤可以使效率更高一些,但是我不知道如何做到这一点。
free_membership_type = MembershipType.all().filter("membership_class =", "Free").filter("live =", True).get()
all_free_users = UserMembershipType.all().filter("membership_active =", True)
all_free_users = all_free_users.filter("membership_type =", free_membership_type).fetch(limit = 999999)
if all_free_users:
for free_user in all_free_users:
activation_status = ActivationStatus.all().filter("user = ", free_user.user).get()
if activation_status and activation_status.activated:
documents_left = WeeklyLimits.all().filter("user = ", free_user.user).get()
if documents_left > 0:
do something...
代码使用的模型是:
class MembershipType(db.Model):
membership_class = db.StringProperty()
membership_code = db.StringProperty()
live = db.BooleanProperty(default = False)
class UserMembershipType(db.Model):
user = db.ReferenceProperty(UserModel)
membership_type = db.ReferenceProperty(MembershipType)
membership_active = db.BooleanProperty(default = False)
class ActivationStatus(db.Model):
user = db.ReferenceProperty(UserModel)
activated = db.BooleanProperty(default = False)
class WeeklyLimits(db.Model):
user = db.ReferenceProperty(UserModel)
membership_type = db.ReferenceProperty(MembershipType)
documents_left = db.IntegerProperty(default = 0)
我在生产中使用的代码确实更好地利用了各种实体的缓存,但for循环仍然需要遍历一堆用户才能最终找到需要进行操作的少数几个。理想情况下,我会过滤掉所有不符合标准的用户,然后才开始循环浏览用户列表 - 我是否可以使用某种神奇子弹来实现这一目标?
答案 0 :(得分:2)
您可以通过将数据更紧密地存储在单个模型中来改善这一点。例如,单个实体类UserMembership
可以包含您需要的所有字段,并且您可以执行单个查询:
.filter("membership_type =", "FREE").filter("status =", "ACTIVE").filter("documentsLeft >", 0)
这需要定义一个额外的索引,但运行速度要快得多。
答案 1 :(得分:2)
您可能正在寻找的魔力是非规范化。在我看来,这些类都可以有意义地组合成一个模型:
class Membership(db.Model):
user = db.ReferenceProperty(UserModel)
membership_class = db.StringProperty()
membership_code = db.StringProperty()
live = db.BooleanProperty(default = False)
membership_active = db.BooleanProperty(default = False)
activated = db.BooleanProperty(default = False)
documents_left = db.IntegerProperty(default = 0)
然后,您可以使用一个查询来完成所有过滤。
过度规范化是AppEngine开发中常见的反模式。您发布的模型看起来也可能是关系数据库的表定义(尽管,它是否可以说比它更加划分区域化,而且AppEngine的数据存储非常不关系数据库数据库中。
您是否看到将所有这些字段存储在单个模型中的任何缺点?
答案 2 :(得分:1)
如果您希望避免按照其他两个答案的建议对数据进行非规范化,您还可以考虑使用Google的新SQL服务而不是普通数据存储:http://googleappengine.blogspot.com/2011/10/google-cloud-sql-your-database-in-cloud.html
使用SQL,您可以在单个查询中完成所有这些操作,即使使用单独的实体也是如此。