0

プレーヤーの進行状況を MySQL データベースに保存するオンライン ゲームを開発しており、パフォーマンスを最適化しようとしています。このデータは、特定の進捗実績に対応する ID の形式になります。これらの「成果」は、NPC との会話、クエストの開始、クエストの完了などで構成されるため、ID は特定の順序でデータベースに追加されません。私は現在、これらのシナリオのうち、実績データを保存する方法を決定するのに苦労しています:

1)「プレーヤー」テーブルのコンマ区切りのテキスト フィールド (32,2,53,1,3,5 など) として。実績がトリガーされるたびに、対応する ID がテキスト フィールドの末尾に追加されます。PHP 側は、strpos を使用してチェックを実行します。

2) Player_Progress テーブル内にレコードとして保存されます。これは、プレーヤーごとに膨大な数 (~100) のレコードを潜在的に意味する可能性があり、これがパフォーマンスにどのように影響するかはわかりません.

区切られたフィールドが嫌われていることは理解していますが、データが数回しかチェックされておらず、追加されている (削除されていない) だけであるため、この状況で正規化が少し過剰になるのではないかと考えていました。

4

1 に答える 1

2

常にすべてをゲームクライアントに読み込み、そこに状態を永続化 (おそらく辞書またはハッシュテーブル) し、データベースをフラットな永続化/シリアル化ストアとして使用する場合、それは問題ではないと主張できます。しかし、この行は私を捕まえました:

PHP 側は、strpos を使用してチェックを実行します。

これは、個々の実績についてクエリを実行したいように思えます。ここでは、次の 2 つの理由から、データベースを使用することをお勧めします。

  1. サーバーにリクエストを送信するたびに、文字列全体を読み取って逆シリアル化する必要はありません。状態は、何らかの努力なしではリクエスト間で保持されません。上記のステートメントを読んで、このゲームはローカル クライアントではなく、常にサーバーにリクエストを送信するブラウザで実行されていることを意味します。
  2. データベースの力を活用できます。

正規化されたデータベースを使用すると、特定のプレーヤーの実績を次のクエリで簡単に確認できます。

SELECT 1
FROM achievements
WHERE playerId = @playerId
AND achievementId = @achievementId

適切なインデックスがあれば、これは非常に高速です。

文字列がある場合は、最初にシリアル化された BLOB をデータベースから取得する必要があります。次に、それを解析して使用可能なデータ構造にするか、各文字を 1 つずつ調べて探しているデータを見つけます。これは、より多くのオーバーヘッドのようです。

補足として、プレイヤー 1 人あたり 100 行は、たとえ 1,000,000 人のプレイヤーがいたとしても、実際には「多くの」行ではありません。

于 2014-03-08T04:29:35.880 に答える