我正在为我的游戏开发一个高分的网络服务,它正在Google App Engine上运行。
我的游戏有5个难度,所以我最初有5个棋盘,每个棋盘都有条目(player_login,得分和时间)。如果玩家提交的分数低于之前的分数,则会被解雇,因此每个玩家只保留最高分。
但为了增加更多的乐趣,我决定包括每日/每周/每月/每年的高分表。所以我为每个难度创建了5个板,使其成为25个板。提交分数后,会将其保存到每个板中,并且应该每天/每周/每月/每年清除这些板。
这是通过调用的cron作业发生的,并删除特定板上的所有条目。
问题出现了:看起来从数据存储中删除条目很慢。从我的测试每日清理看起来删除单个条目大约需要200毫秒。
在最糟糕的情况下,如果游戏非常受欢迎,并且会有10万玩家,而且他们每个人都会在年度董事会中有一个条目,则需要10万* 0.012秒= 12 000秒(3小时!!)清除那块板子。我认为我们可以在App Engine中获得长达30秒的作业,因此这不起作用。
我正在删除following code (thanks to Nick Johnson):
q = Score.all(keys_only=True).filter('b = ',boardToClear)
results = q.fetch(500)
while results:
self.response.out.write("deleting one batch;")
db.delete(results)
q = Score.all(keys_only=True).filter('b = ',boardToClear).with_cursor(q.cursor())
results = q.fetch(500)
你建议我怎么处理这个问题?
我想到的一种方法是使用任务队列并删除比每个板中允许的旧分数,即已过期但数量较少的分数。这样我就不会达到一个任务的CPU限制,但是清理不会(几乎)瞬间完成,因此我的12000秒长清理将分成1 200个任务,每个任务大约10秒。
但我认为有些事我做错了,在关系数据库中完成这种操作会快得多。我的数据存储和评分方法可能有问题,因为被锁定在RDBMS思维模式中。
答案 0 :(得分:4)
首先,提出一些小建议:
keys_only
查询,然后立即在整个密钥列表上调用db.delete()
。但这些可能无法从根本上解决您的问题。我认为没有办法解决删除大量记录(数十万,比如说)的事实需要一些时间。我不确定这对你的用例来说是一个大问题,因为我可以看到一些有用的技术。
答案 1 :(得分:3)
批量删除实体。虽然单个删除需要相当长的时间(尽管200毫秒似乎非常高),但批量删除不再需要,因为它们会并行删除所有实体。任务队列和cron作业现在可以运行长达10分钟,因此超时不应成为问题。