简体   繁体   中英

MySQL JPQL query performance issue

I'm building a game which I intend to be a persistent online world (like an MMO, but probably not a massive number of players.) I'm making a game map by just creating a 2d grid of "tiles." I've got my tiles persisting to my database just fine, and I've got a web page UI (via Vaadin) set up so I can view them just fine. So far I've been viewing them most often in a 20x20 grid.

Up to now, it seemed to be going great. I could persist a couple sets of 10,000 tiles, and scroll around looking at them and redisplaying the tiles was nearly instantaneous. Today, though, I decided to persist a whole bunch of tiles (633,460 to be exact) to see what it was like with a more realistic number of tiles in the database. Now I'm having some significant performance issues scrolling around the map, because my MySQL database seems to be having a difficult time handling that many tiles.

I'm using JPA 2.0 backed by Hibernate. Even when I go straight to the database and run a SQL query, the response times are super slow.

SELECT * FROM game.landtile WHERE xcoor < 999999061 AND xcoor >  999999040
AND ycoor > 1000000140 AND ycoor < 1000000161;

I just ran that query to get 400 landtiles and it had a 3.5 second duration and 7.25 second fetch time directly in MySQL! If I run the same query a second time it has a 0.5 second duration and a 0.1 second fetch time. 500 miliseconds I could live with ... 7,000 I cannot.

My entity for the landtile looks like this:

@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;

There are also another 18 simple int columns I didn't list here.

So basically I'm hoping you guys could help me figure out what my options are. As you can see there are a lot of relationships going on between a landtile and my other models, and for a game like this the whole data set itself is highly relational, which is why I went with a SQL database in the first place. But now I'm worried the performance is just going to be so bad that I should stop developing new features, and rework my entire DAO layer (hopefully it would only have to be that ...) to use a NoSQL database, and deal with all my relationships in the java.

Looks like MongoDB has built in support for 2d grids:

http://blog.codecentric.de/en/2012/02/spring-data-mongodb-geospatial-queries/

I was planning on probably hosting my game on Amazon and using Amazon Elasti-cache. Would it be possible for my game map data to mostly linger in that 2nd level cache (via hibernate) and therefore I wouldn't have this horrible performance? I really think the only real performance issue I'll run into with MySQL is going to be scrolling around the dumb map!

My data is spatial data, and MySQL's InnoDB engine does not support spatial indexes. The MyISAM engine does, but it does not support transactions or foreign keys. See the MySQL documentation .

Instead of sacrificing transactions and foreign keys, I decided to use a database that supports complex relationships, transactions, and foreign keys, so I switched my entire project to use the Neo4j graph database .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM