我正构建一个游戏,我打算成为一个持久的在线世界(就像一个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个landtiles,它在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列。
所以基本上我希望你们能帮助我弄清楚我的选择是什么。正如你所看到的那样,在landtile和我的其他模型之间存在很多关系,对于像这样的游戏,整个数据集本身是高度关系的,这就是为什么我首先使用SQL数据库。但是现在我担心性能会变得如此糟糕以至于我应该停止开发新功能,并重新编写我的整个DAO层(希望它只需要......)来使用NoSQL数据库,并处理我在java中的所有关系。
看起来MongoDB内置了对2d网格的支持:
http://blog.codecentric.de/en/2012/02/spring-data-mongodb-geospatial-queries/
我计划在亚马逊上使用Amazon Elasti-cache托管我的游戏。我的游戏地图数据是否有可能大部分停留在第二级缓存中(通过休眠),因此我不会有这种糟糕的表现?我真的认为我遇到的唯一真正的性能问题是围绕哑图滚动!
答案 0 :(得分:0)
我的数据是空间数据,MySQL的InnoDB引擎不支持空间索引。 MyISAM引擎可以,但它不支持事务或外键。请参阅the MySQL documentation。
我决定使用支持复杂关系,事务和外键的数据库,而不是牺牲事务和外键,所以我将整个项目切换为使用Neo4j graph database。