简体   繁体   中英

MySQL select performance issue with JDBC

I'm having a performance issue with MySQL (v5.5) while running a local Java application using mysql-connector v5.1.30

I have 2 tables called A and B. I run something like this:

PreparedStatement stmtA = conn.prepareStatement("select x, y, z, u, v, w from A");
PreparedStatement stmtB = conn.prepareStatement("select val from B where something = ?");
ResultSet result = stmtA.executeQuery();
while ( resultA.next() ){
    // do something with result row
    if (some condition) { // true approx. 80% of the time
        ResultSet resultB = stmtB.executeQuery(some_value_from_resultA);
        // do something with result row  
        resultB.close();
    }
}
stmtA.close();

The problem is that this takes ~12 minutes to complete every time. Here's a few relevant bits of information:

  • The mysqld process is using 95-99% CPU for the 12 minute duration
  • The java process is using 1-4% CPU for the 12 minute duration
  • Memory usage for both processes is negligable
  • Table A has 65,000 records, 18 columns (all VARCHAR except for Id) and uses MYISAM
  • Table B has 51,000 records, 4 columns (3 INT and 1 VARCHAR) and uses MYISAM
  • There is no index/key on the Table B column that I'm querying
  • I'm running Ubuntu 12.04 with a Core i5 and 4GB RAM

Aside from the fact that the CPU usage of the mysql process is crazy, the reason I think there is a problem is because the application has additional functionality that runs an almost identical method against a different database table. This table has a similar number of columns to table A (also using MYISAM) but one big difference is that there is no table B here. So it works the same as above but without having to query a second table while iterating the rows of the first table.

This other table has 4,500 rows and the iteration takes less than 1 second.

So it would appear that the nested query of table B is causing the problem, but I'm not sure. I have limited experience with MySQL. If you need any more info, please ask.

You might want to pre-load or cache the results of the queries you run on table B. Since table B doesn't have many records, you can afford to load it into a map.

You have two options :

  1. pre-load the entire B table and create a Map of something (key) and val (value). Then access that map instead of running 0.8*65000 queries. That would be most effective if something has many unique values and your B queries search for many of them.
  2. Store the result of each query on B in the map and check that map before running these queries. There's not point in loading the same data twice. That would be more efficient in terms of memory if you only use a small subset of the something values in your B query.

Adding an index on table B would also help.

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