質問: 質問自体はタイトルの通りなのですが、理解しにくい質問なので例を書かせていただきます。 例えば、経験値とレベルが存在するゲームのDBを設計したいとします。 経験値は一定値たまると、レベルが上昇します。そしてその経験値とレベルの対応表は別のテーブルで、マスターデータとして持っているとします。 この時に、レベルをDBに入れるべきか、入れるとしたらどのようにテーブルを設計するのか、で悩んでいます。 レベルは経験値とマスターデータから読み出し、アプリケーションないで計算して算出できるため、厳密には保存する必要性がありません。 しかしレベルに依存するデータが色々(パラメータ上限とか、ダメージ算出とか)あった場合、毎回2つのテーブルからデータを読み込んで計算することになりため、DBの負荷とCPUのリソースを使用します。 ではレベルをDBに持たせてしまうと、今後はDB内に保存したレベルと経験値の不整合が起こるリスクを抱える事になります。 このような、特定のデータから算出できる値はどのように扱うべきでしょうか? よろしければご回答よろしくお願いします。
回答: 「毎回計算するだけでいい値」なら永続化しないのが理想だとは思いますが、それでパフォーマンスの要件を満たせないのであれば、キャッシュを作るしかありません。 といっても、例えばプレイヤー自身の情報として使う場合は「アプリケーションから短期間で特定ユーザーのレベル情報が繰り返し必要になる」わけですから、DBではなく、もっとアプリケーションに近い場所で揮発性のキャッシュとして持ってもよいでしょう。 計算結果を含めた一覧を取得したり、それを別テーブルとJOINしたり、といったDB内でのパフォーマンスを向上させたいなら、キャッシュもDB内に収めるのが効果的かもしれませんが。 ところでゲームの場合、レベルが変動すればレベルアップの処理が入ることが多いかと思います。 その中にはレベルをインクリメントするほかにも、ステータス値が変動したり、新たなスキルを覚えたり、特別なイベントが発生したり、と様々な**変化**が生じます。これら全てをレベルの数値、ひいては経験値から計算するのでしょうか。仮にレベルだけ計算で求めるとすると、今度はレベルとその他の変化状態に不整合が生じる可能性がある、とも言えませんか? またオンラインゲームでは後からバランス調整として必要経験値を変更する場合がありますが、現在の累積経験値と新しいテーブルでレベルを計算すると一度にレベルが大きく変動することになります。この時にも、現在のレベルを記録しておけば、**不整合が発生していることをきっかけに**再計算とレベルアップ(もしくはダウン)の処理が行えます。この場合「現在のレベル」はただのキャッシュではなく、永続化すべき値ですね。