MySQL JPQL查询性能问题

时间:2013-02-22 07:51:54

标签: java mysql hibernate mongodb

我正构建一个游戏,我打算成为一个持久的在线世界(就像一个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托管我的游戏。我的游戏地图数据是否有可能大部分停留在第二级缓存中(通过休眠),因此我不会有这种糟糕的表现?我真的认为我遇到的唯一真正的性能问题是围绕哑图滚动!

1 个答案:

答案 0 :(得分:0)

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

我决定使用支持复杂关系,事务和外键的数据库,而不是牺牲事务和外键,所以我将整个项目切换为使用Neo4j graph database