永続的なオンラインの世界 (MMO のようなものですが、おそらく膨大な数のプレイヤーではない) を意図したゲームを構築しています。「タイル」の 2D グリッドを作成するだけでゲーム マップを作成しています。タイルはデータベースに正常に保持されており、(Vaadin を介して) Web ページ UI がセットアップされているので、それらを正常に表示できます。これまでのところ、私はそれらを 20x20 グリッドで最も頻繁に見てきました。
これまでのところ、それはうまくいっているように見えました。10,000 個のタイルのセットをいくつか保持し、それらをスクロールして見て、タイルを再表示するのはほぼ瞬時でした。しかし今日は、データベース内のより現実的な数のタイルがどのようなものかを確認するために、大量のタイル (正確には 633,460) を保持することにしました。私のMySQLデータベースは多くのタイルを処理するのに苦労しているようです.
Hibernate に裏打ちされた JPA 2.0 を使用しています。データベースに直接アクセスして SQL クエリを実行しても、応答時間が非常に遅くなります。
SELECT * FROM game.landtile WHERE xcoor < 999999061 AND xcoor > 999999040
AND ycoor > 1000000140 AND ycoor < 1000000161;
そのクエリを実行して 400 個のランドタイルを取得したところ、MySQL で直接 3.5 秒の期間と 7.25 秒のフェッチ時間がかかりました! 同じクエリを 2 回実行すると、実行時間は 0.5 秒、フェッチ時間は 0.1 秒になります。500 ミリ秒なら耐えられますが、7,000 ミリ秒は耐えられません。
Landtile のエンティティは次のようになります。
@Entity
@Table(name = "LandTile", uniqueConstraints = {@UniqueConstraint(columnNames={"XCoor", "YCoor"})})
public class LandTile extends AbstractMapValues implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@Column(name = "LandTileId")
private String landTileId;
@Column(name = "XCoor")
@Index(name = "XCoordinateIndex")
@Range(min = 0, max = MAX_MAP_INT)
private int xCoor;
@Column(name = "YCoor")
@Index(name = "YCoordinateIndex")
@Range(min = 0, max = MAX_MAP_INT)
private int yCoor;
@OneToOne(cascade = CascadeType.ALL)
private Building building;
@OneToOne(cascade = CascadeType.ALL)
private Road road;
private boolean river;
@OneToMany(mappedBy="expeditionLocationLandTile")
private Set<Expedition> expeditionsAtThisLocation;
@ManyToMany(
mappedBy = "discoveredLandTiles",
targetEntity = Player.class
)
private Set<Player> playersThatHaveDiscovered;
@ManyToMany(
mappedBy = "routeListOfLandTiles",
targetEntity = Expedition.class
)
private List<Expedition> expeditionRouteThisIsPartOf;
@ManyToOne
@JoinColumn(name="FiefdomOfCapitalCity", unique=true)
private Fiefdom fiefdomOfCapitalCity;
@ManyToOne
@JoinColumn(name="ActualOwningFiefdomId", unique=true)
private Fiefdom actualOwningFiefdom;
@ManyToOne
@JoinColumn(name="DefaultOwningFiefdomId", unique=true)
private Fiefdom defaultOwningFiefdom;
ここには記載していない 18 個の単純な int 列もあります。
基本的に、皆さんが私の選択肢が何であるかを理解するのを手伝ってくれることを願っています. ご覧のとおり、landtile と他のモデルとの間には多くの関係があり、このようなゲームでは、データ セット全体が非常に関係性が高いため、最初に SQL データベースを使用しました。しかし今は、パフォーマンスが非常に悪くなるのではないかと心配しているので、新しい機能の開発をやめて、DAO レイヤー全体を作り直して (できればそれだけでいいのに...)、NoSQL データベースを使用して対処する必要があります。 Javaでの私のすべての関係で。
MongoDB には 2D グリッドのサポートが組み込まれているようです。
http://blog.codecentric.de/en/2012/02/spring-data-mongodb-geospatial-queries/
おそらく、Amazon でゲームをホストし、Amazon Elasti-cache を使用することを計画していました。ゲーム マップ データの大部分が (休止状態を介して) 第 2 レベルのキャッシュに残っている可能性はありますか? MySQL で遭遇する唯一の実際のパフォーマンスの問題は、ダムマップをスクロールすることだと思います!