10

これは私がかなり長い間疑問に思っていたことであり、まだ本当の (良い) 解決策を見ていません。これは、多くのゲームが抱えていると私が想像する問題であり、解決方法を簡単に考えることができません (まあ)。アイデアは大歓迎ですが、これは具体的な問題ではないので、詳細を尋ねる必要はありません。(そしてあなたが作ったものを説明してください)。

さて、多くのゲームには (インベントリ) アイテムの概念があり、多くの場合、何百もの異なる種類のアイテムがあり、すべてが非常に多様なデータ構造を持つことがよくあります。非常に単純なアイテム (「岩」) もあれば、持つことができるアイテムもあります。非常識な複雑さ、またはそれらの背後にあるデータ (「本」、「プログラムされたコンピューター チップ」、「より多くのアイテムが入ったコンテナー」) など。

さて、そのようなプログラミングは簡単です。すべてにインターフェースを実装させるか、抽象ルート項目を拡張するだけです。プログラミングの世界のオブジェクトは、内側と外側が同じように見える必要はないため、どのタイプのアイテムでもプライベート フィールドの量と種類に問題はありません。

しかし、データベースのシリアル化に関しては (バイナリ シリアル化はもちろん問題ありません)、ジレンマに直面しています: たとえば、典型的な SQL データベースでそれをどのように表現しますか?

私が見た解決策のいくつかの試みは、満足のいくものではありません:

  1. アイテムのバイナリ シリアル化。データベースは ID と BLOB のみを保持します。

    • 長所: 実装に 10 秒ほどかかります。
    • 短所: 基本的にすべてのデータベース機能を犠牲にし、保守が難しく、リファクタリングがほぼ不可能です。
  2. 項目タイプごとの表。

    • 長所:クリーンで柔軟。
    • 短所: 多種多様なテーブルが何百もあり、SQL にはテーブル/タイプの「参照」の概念がないため、項目を検索するたびにそれらすべてを照会する必要があります。
  3. すべてのアイテムで使用されていない多くのフィールドを持つ 1 つのテーブル。

    • 長所: 実装に 10 秒ほどかかりますが、それでも検索可能です。
    • 短所: スペースの浪費、パフォーマンス、使用中のフィールドをデータベースからわかりにくくする。
  4. 同様のアイテムが一緒にスローされ、異なるデータに同じフィールドを使用するストレージ用のいくつかの「基本プロファイル」を持ついくつかのテーブル。

    • プロの:私は何も持っていません。
    • 短所: スペースの浪費、パフォーマンス、使用中のフィールドをデータベースからわかりにくくする。

どんなアイデアがありますか?良くも悪くも機能する別のデザインを見たことがありますか?

4

6 に答える 6

4

It depends if you need to sort, filter, count, or analyze those attribute.

If you use EAV, then you will screw yourself nicely. Try doing reports on an EAV schema.

The best option is to use Table Inheritance:

PRODUCT
id pk
type
att1

PRODUCT_X
id pk fk PRODUCT
att2
att3

PRODUCT_Y
id pk fk PRODUCT
att4
att 5

For attributes that you don't need to search/sort/analyze, then use a blob or xml

于 2013-03-01T19:31:50.500 に答える
2

2 つの選択肢があります。

  1. 基本型用の 1 つのテーブルと、特殊な型の各「クラス」用の補足テーブル。

    このスキーマでは、すべての「オブジェクト」に共通のプロパティが 1 つのテーブルに格納されるため、ゲーム内のすべてのオブジェクトに対して一意のレコードが作成されます。本、コンテナ、使用可能なアイテムなどの特殊なタイプの場合、それらのアイテムが必要とするプロパティまたは関係の一意のセットごとに別のテーブルがあります。したがって、すべての特殊タイプは、特定の特殊タイプ テーブル内の基本オブジェクト レコードと補助レコードの 2 つのレコードで表されます。

    長所: カスタム ドメイン、チェック、xml 処理など、データベースの列ベースの機能を使用できます。特定のタイプに対してより単純なトリガーを設定できます。あなたのクエリは、懸念が分かれている点で正確に異なります。

    短所: 多くのオブジェクトに対して 2 つの挿入が必要です。

  2. 特殊なタイプのデータには、「kind」列挙型フィールドと JSONB のようなフィールドを使用します。

    これは、データベースのヘルプを除いて、#1 または #3 のようなものです。Postgres に JSONB が追加され、古い EAV パターンが改善されました。他のデータベースには、同様の複雑なフィールド タイプがあります。この戦略では、JSONB フィールドに隠しておく独自のミニ スキーマを展開します。kind フィールドは、その JSONB フィールドで期待される内容を宣言します。

    長所: クエリで特殊なタイプのデータを抽出できます。チェック制約を追加し、対処する単純なスキーマを持つことができます。データが異種であっても、インデックス作成の恩恵を受けることができます。クエリと挿入は簡単です。

    短所: JSONB のようなフィールド内のデータ型はかなり制限されており、独自の検証を行う必要があります。

于 2018-03-28T20:17:35.847 に答える
1

これは何百万回も前にここで尋ねられたと確信していますが、質問で説明したオプションに加えて、非常に柔軟ですが、独自の短所がある EAV スキーマを見ることができます。

もう 1 つの選択肢は、リレーショナルではないデータベース システムです。オブジェクト データベースだけでなく、さまざまなキー/バリュー ストアやドキュメント データベースもあります。

通常、柔軟な属性に対してクエリを実行する必要がある場合、これらすべてがある程度分解されます。ただし、これは一種の本質的な問題です。概念的に、構造化されていないものを正確にクエリすることの本当の意味は何ですか?

于 2013-03-01T19:36:53.600 に答える
1

ゲームのコンテキストでこれを解決しようとしているように見えるので、コンポーネントベースのアプローチを検討できるかもしれません. 私は個人的にこれをまだ試していないと言わざるを得ませんが、しばらく調べていて、似たようなことが適用できるようです.

ゲーム内のすべてのエンティティは、基本的にコンポーネントの袋になるという考えです。これらのコンポーネントはPositionEnergyまたは在庫ケースの場合、Collectableたとえば です。次に、このCollectableコンポーネントに、カテゴリ、numItems などのカスタム フィールドを追加できます。

インベントリをレンダリングする場合は、Collectableコンポーネントを持つアイテムについてエンティティ システムにクエリを実行するだけです。

これをどのようにDBに保存できますか?コンポーネントを独自のテーブルで個別に定義してから、エンティティ (それぞれ独自のテーブルでも) に対して、これらのコンポーネントを参照する ID の配列を保持する「コンポーネント」列を追加します。これらの ID は実質的に外部キーのようなものですが、これがリレーショナル データベースで物事をモデル化する正確な方法ではないことは承知していますが、アイデアは理解できます。

次に、実行時にエンティティとそのコンポーネントをロードするときに、ロードされるコンポーネントに基づいて、コンポーネントのバッグに対応するフラグを設定して、このエンティティにどのコンポーネントがあるかを知ることができ、クエリ可能になります。

これは、コンポーネントベースのエンティティ システムに関する興味深い読み物です

于 2013-03-01T23:19:00.123 に答える
1

まず第一に、実際のデータベースの同時実行性、スケーラビリティ、および ACID トランザクションが実際に必要ですか? MMO を構築している場合を除き、ゲームの構造はメモリに収まる可能性が高いため、そこで直接検索したり操作したりできます。このようなシナリオでは、「データベース」はシリアル化されたオブジェクトの単なるストアであり、ファイル システムに置き換えることができます。


必要があると判断した場合 (データベースが必要)、データ管理の観点から「原子性」が何を意味するのかを理解することが重要です。

たとえば、ゲーム アイテムに多数の属性があり、これらの属性のいずれもデータベース レベルで個別に操作されていない場合 (アプリケーション レベルで操作できる場合でも)、データからは「アトミック」と見なすことができます。経営視点。OTOH、これらの属性の一部でアイテムを検索する必要がある場合は、データベースでそれらをインデックス化する適切な方法が必要になります。これは通常、それらが別のフィールドである必要があることを意味します。

データベースの観点から「表示」する必要がある属性と「非表示」にする必要がある属性を特定したら、後者を BLOB (または何でも) にシリアル化し、それらを忘れて前者の構造化に集中します。

それが楽しみの始まりであり、合理的な結果を得るには、おそらく「上記のすべて」の戦略を使用する必要があります。

ところで、一部のデータベースは、異種データ構造に入る「深い」インデックスをサポートしています。たとえば、Oracle のXMLIndexを見てみましょう。ただし、ゲームに Oracle を使用することはないと思います。

于 2013-03-01T22:51:59.147 に答える
1

はい、このようなデータベース形式を設計するのは面倒です。私は通知システムを設計していますが、同じ問題に遭遇しました。ただし、私の通知システムはあなたのものほど複雑ではありません。保持するデータは、せいぜい ID とユーザー名です。私の現在の解決策は、1 と 3 の組み合わせです。すべての通知とは異なるデータをシリアル化し、2 つのユーザー名に列を使用します (2 つまたは 1 つある場合もあります)。私はそのデザインが嫌いなので、方法 2 を敬遠しますが、それはおそらく私だけです。

ただし、余裕がある場合は、RDBMS の領域外で考えることをお勧めします。特にアイテム 1 とアイテム 2 が異なる場合は、非 RDBMS (特にキー/値ストレージ) がこれらのデータを格納するのにより適しているように思えます。各アイテムからたくさん。

于 2013-03-01T18:48:52.193 に答える