1

Django 1.6 と PostgreSQL 9.1 を使用して、オンライン ゲームのプレイヤー統計を表示する Web アプリケーションを作成しています。オンラインのすべてのプレイヤーをフェッチし、テーブルに挿入/更新するスクリプトを django-extensions の「runscript」を使用して作成しました。このスクリプトは、cron を使用して 1 時間に 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]'. :)

4

1 に答える 1

1

クエリの数を減らしたい場合は、次のことをお勧めします。各プレイヤーに対して update() を直接呼び出すと、更新された行数が返されます。カウントが 0 (プレイヤーが新しいことを意味する) の場合は、プレイヤー データを入力します。一時的なリストに。フェッチしたすべてのプレイヤーの処理が完了したら、bulk_create() を使用して、1 つの SQL ステートメントですべての新しいプレイヤーを挿入します。

M+N 人のプレーヤー (M は新規、N は更新)、クエリの数があるとします。

前: (M+N) 選択 + M 挿入 + N 更新

後: (M+N) 回の更新 + 1 回の一括挿入。

于 2014-03-15T03:52:35.167 に答える