0

我正在构建一个游戏,我打算成为一个持久的在线世界(就像一个 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 时遇到的唯一真正的性能问题是在哑图上滚动!

4

1 回答 1

0

我的数据是空间数据,MySQL的InnoDB引擎不支持空间索引。MyISAM 引擎支持,但它不支持事务或外键。请参阅MySQL 文档

我没有牺牲事务和外键,而是决定使用支持复杂关系、事务和外键的数据库,因此我将整个项目切换为使用Neo4j 图数据库

于 2013-03-04T02:27:19.440 回答