我正在构建一个游戏,我打算成为一个持久的在线世界(就像一个 MMO,但可能不是大量的玩家。)我正在通过创建一个 2d 网格“瓷砖”来制作游戏地图。我的磁贴可以很好地保存到我的数据库中,并且我已经设置了一个网页 UI(通过 Vaadin),因此我可以很好地查看它们。到目前为止,我最常在 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 秒的获取时间!如果我第二次运行相同的查询,它的持续时间为 0.5 秒,获取时间为 0.1 秒。500 毫秒我可以忍受...... 7,000 我不能。
我的地块实体如下所示:
@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 列我没有在这里列出。
所以基本上我希望你们能帮助我弄清楚我的选择是什么。如您所见,地块和我的其他模型之间存在很多关系,对于这样的游戏,整个数据集本身是高度相关的,这就是我首先使用 SQL 数据库的原因。但现在我担心性能会变得如此糟糕,以至于我应该停止开发新功能,并重新设计我的整个 DAO 层(希望它只需要那样......)以使用 NoSQL 数据库,并处理与我在 java 中的所有关系。
看起来 MongoDB 已经内置了对 2d 网格的支持:
http://blog.codecentric.de/en/2012/02/spring-data-mongodb-geospatial-queries/
我计划在 Amazon 上托管我的游戏并使用 Amazon Elasti-cache。我的游戏地图数据是否有可能主要停留在二级缓存中(通过休眠),因此我不会有这种可怕的性能?我真的认为我在使用 MySQL 时遇到的唯一真正的性能问题是在哑图上滚动!