【发布时间】:2014-01-16 06:49:10
【问题描述】:
我正在使用 Django 1.6 和 PostgreSQL 9.1 编写一个 Web 应用程序,它将显示在线游戏的玩家统计信息。我使用 django-extensions “runscript” 创建了一个脚本,该脚本获取所有在线玩家并将其插入/更新到我的表中。该脚本使用 cron 每小时执行 4 次。我需要插入或更新,因为播放器可能已经在表中(因此应该更新)或不在表中。
对于我的问题:高峰时段大约有 25,000 名玩家在线,我不确定应该如何优化这一点(最小化 hdd i/o)。到目前为止,我是这样做的:
@transaction.commit_manually
def run():
for fetched_player in FetchPlayers():
defaults = {
'level': fetched_player['level'],
'server': fetched_player['server'],
'last_seen': date.today(),
}
player, created = Player.objects.get_or_create(name=fetched_player['name'], defaults)
if not created:
player.level = fetched_player['level']
if player.server != fetched_player['server']:
# I save this info to another table
player.server = fetched_player['server']
player.last_seen = date.today()
player.save()
transaction.commit()
绕过 Django 并使用 psycopg2 或类似工具访问数据库会更快吗?当“其他人”修改数据库时,Django 会感到困惑吗?注意 Django 只读取数据库,所有的写入都由这个脚本完成。
如何(使用 Django 或 psycopg2)从数据库中批量获取播放器,更新找到的播放器,然后插入未找到的播放器?如果这甚至可能?查询会变得很大:'SELECT * FROM player WHERE name = name[0] OR name = name[1] OR ... OR name[25000]'。 :)
【问题讨论】:
-
也许你可以在第一次插入播放器时做一个注释,所以
fetched_player将包含一个信息,如果播放器是新的并且应该插入,或者它不是并且应该更新 - 这个会让事情变得容易得多。您根本不必从数据库中获取数据。 -
@LudwikTrammer 我不确定我理解你的意思。 FetchPlayers() 只是检索和解析 HTML 文档。这些“笔记”应该存储在哪里?
-
如果没有任何对象字段被修改,Django'smart'是否足够不执行插入查询?如果我将一个字段设置为与它已有的值相同的值,然后调用 .save() 会怎样?我尝试对所有属性进行检查(就像 player.server != fetched_player['server']),然后仅在任何属性确实发生更改时才调用 .save() 。这似乎已经最小化了一些 I/O,请参阅:pastebin.com/RfWbUGYJ 和 imgur.com/cKlsLJ4 我还能做些什么改进?
-
哦,好的。
FetchPlayers()使用了你无法控制的数据源 - 我一开始没有得到这个。 -
关于改进的问题。这一切都取决于 - 如果插入相对较少(这听起来很合理),最好: 1. 检查对象是否存在
.exists()2. 如果它确实使用.update()更新 3. 如果它不插入 @ 987654328@ 这样您就不必从数据库中获取整个对象。这可能会更快,但确保它的唯一方法是尝试并查看。
标签: django postgresql psycopg2 django-postgresql