优化批量更新/插入

时间:2013-12-29 02:56:28

标签: django postgresql psycopg2 django-postgresql

我正在编写一个Web应用程序,它将使用Django 1.6和PostgreSQL 9.1显示在线游戏的玩家统计数据。我使用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 ...或name [25000]'。 :)

1 个答案:

答案 0 :(得分:0)

如果您想减少查询次数,我建议: 直接为每个玩家调用update(),返回更新的行数,如果计数为0(表示玩家是新的),则将玩家数据放入临时列表中。完成所有获取的播放器后,使用bulk_create()通过一个SQL语句插入所有新播放器。

假设您有M + N个玩家(M new,N更新),查询次数:

之前:(M + N)选择+ M次插入+ N次更新

之后:(M + N)更新+1批量插入。