求解 spring中jdbcTemplate从mysql百万数据查询出50多万条数据很慢

时间:2022-06-07 21:48:46
开始使用mybatis查询很慢,换成jdbcTemplate还是很慢
数据库里面大概有100W条数据,select udid,token,country,language,platform,osVersion from device_info where platform=?这段查询出来大概有50W数据,在程序中查询很慢,数据中查询也就2s左右,求解?可以用分表来解决吗?

public List<Device> findByPlatform(int platform) {
String key = "platform-device-"+platform;
List<Device> devices = (List<Device>) RedisClient.getObject(key);
if(devices == null){
String sql = "select udid,token,country,language,platform,osVersion from device_info where platform=?";
devices = (List<Device>) jdbcTemplate.query(sql, new Object[]{platform}, new DeviceMapper());
                        //这句执行很慢,数据库里面总共100W数据,查询出来大概有50W条数据,数据库执行时间大概2-3s,
                        //求解为什么在程序里面执行这么慢?
}
return devices;

}

12 个解决方案

#1


platform 做个索引

#2


引用 1 楼 whos2002110 的回复:
platform 做个索引


这个可以有,查询条件加个索引,会快很多...


楼主想分表查询? 将数据分开查?

#3


二楼的方法就可以,建议你看看数据库索引。最主要的作用是可以大大加快 数据的检索速度。
索引的作用:               http://blog.csdn.net/pang040328/article/details/4164874
mysql如何创建索引:http://blog.sina.com.cn/s/blog_7522019b01015fcm.html

#4


引用 1 楼 whos2002110 的回复:
platform 做个索引


引用 2 楼 shijing266 的回复:
Quote: 引用 1 楼 whos2002110 的回复:

platform 做个索引


这个可以有,查询条件加个索引,会快很多...


楼主想分表查询? 将数据分开查?


引用 3 楼 innight 的回复:
二楼的方法就可以,建议你看看数据库索引。最主要的作用是可以大大加快 数据的检索速度。
索引的作用:               http://blog.csdn.net/pang040328/article/details/4164874
mysql如何创建索引:http://blog.sina.com.cn/s/blog_7522019b01015fcm.html

不是索引的问题,直接在数据库里面执行脚本也就2-3秒,关键是在java中最后生成list对象这部很慢看下面的代码嘛,while这部分很慢


dbcTemplate.query(sql, new Object[]{platform}, new ResultSetExtractor<List<Device>>() {
@Override
public List<Device> extractData(ResultSet rs) throws SQLException, DataAccessException {
rs.last();
int row = rs.getRow();
List<Device> devices = new ArrayList<Device>(row+10);
rs.beforeFirst();
Device device;
//while循环里面非常慢,前面执行都很快
while (rs.next()) {
device = new Device();
device.setUdid(rs.getString("udid"));
device.setCountry(rs.getString("country"));
device.setLanguage(rs.getString("language"));
device.setOsVersion(rs.getString("osVersion"));
device.setPlatform(rs.getInt("platform"));
device.setToken(rs.getString("token"));
devices.add(device);
}
return devices;
}

#5


new 对象的方式,肯定慢的

#6


引用 5 楼 shijing266 的回复:
new 对象的方式,肯定慢的

new一个对象不慢的,经测试new100W个Device对象非常快的,我觉得问题的瓶颈是ResultSet 遍历这里

#7


为什么要一次查询出这么多的数据呢,这样多占内存,先查出一页再分页展示不行吗?数据库中查询也只是展示了第一页吧。

#8


引用 7 楼 huangan0301 的回复:
为什么要一次查询出这么多的数据呢,这样多占内存,先查出一页再分页展示不行吗?数据库中查询也只是展示了第一页吧。

业务需求,没办法,需要一次性加载到内存中

#9


引用 8 楼 qq467339640 的回复:
Quote: 引用 7 楼 huangan0301 的回复:

为什么要一次查询出这么多的数据呢,这样多占内存,先查出一页再分页展示不行吗?数据库中查询也只是展示了第一页吧。

业务需求,没办法,需要一次性加载到内存中


一次性加载这么多数据到内存!!!!建议你使用文件缓存吧,第一次查询后,把结果集缓存进文件,下次直接读文件
或者使用ehcache做缓存

#10


问题就出现在,你查询出数据再装到java中这个过程中慢,你可以打印一下时间,即每次rs.next()的时间,会发现在把数据装到Java内存里面的时候花费 了大量的时间、
以前做过读取好几G的表,基本要读取一晚上

#11


引用 9 楼 asdf544265772 的回复:
Quote: 引用 8 楼 qq467339640 的回复:

Quote: 引用 7 楼 huangan0301 的回复:

为什么要一次查询出这么多的数据呢,这样多占内存,先查出一页再分页展示不行吗?数据库中查询也只是展示了第一页吧。

业务需求,没办法,需要一次性加载到内存中


一次性加载这么多数据到内存!!!!建议你使用文件缓存吧,第一次查询后,把结果集缓存进文件,下次直接读文件
或者使用ehcache做缓存


引用 10 楼 vtopqx 的回复:
问题就出现在,你查询出数据再装到java中这个过程中慢,你可以打印一下时间,即每次rs.next()的时间,会发现在把数据装到Java内存里面的时候花费 了大量的时间、
以前做过读取好几G的表,基本要读取一晚上

的确就是问题出现在rs.next():没办法了,重新换了数据库,没用mysql,改用mongodb了,百万级数据到内存中也就5-6s这个可以接受了,谢谢各位的回答

#12


引用 9 楼 asdf544265772 的回复:
Quote: 引用 8 楼 qq467339640 的回复:

Quote: 引用 7 楼 huangan0301 的回复:

为什么要一次查询出这么多的数据呢,这样多占内存,先查出一页再分页展示不行吗?数据库中查询也只是展示了第一页吧。

业务需求,没办法,需要一次性加载到内存中


一次性加载这么多数据到内存!!!!建议你使用文件缓存吧,第一次查询后,把结果集缓存进文件,下次直接读文件
或者使用ehcache做缓存

缓存没多大用,数据库里面的数据更新比较频繁的

#1


platform 做个索引

#2


引用 1 楼 whos2002110 的回复:
platform 做个索引


这个可以有,查询条件加个索引,会快很多...


楼主想分表查询? 将数据分开查?

#3


二楼的方法就可以,建议你看看数据库索引。最主要的作用是可以大大加快 数据的检索速度。
索引的作用:               http://blog.csdn.net/pang040328/article/details/4164874
mysql如何创建索引:http://blog.sina.com.cn/s/blog_7522019b01015fcm.html

#4


引用 1 楼 whos2002110 的回复:
platform 做个索引


引用 2 楼 shijing266 的回复:
Quote: 引用 1 楼 whos2002110 的回复:

platform 做个索引


这个可以有,查询条件加个索引,会快很多...


楼主想分表查询? 将数据分开查?


引用 3 楼 innight 的回复:
二楼的方法就可以,建议你看看数据库索引。最主要的作用是可以大大加快 数据的检索速度。
索引的作用:               http://blog.csdn.net/pang040328/article/details/4164874
mysql如何创建索引:http://blog.sina.com.cn/s/blog_7522019b01015fcm.html

不是索引的问题,直接在数据库里面执行脚本也就2-3秒,关键是在java中最后生成list对象这部很慢看下面的代码嘛,while这部分很慢


dbcTemplate.query(sql, new Object[]{platform}, new ResultSetExtractor<List<Device>>() {
@Override
public List<Device> extractData(ResultSet rs) throws SQLException, DataAccessException {
rs.last();
int row = rs.getRow();
List<Device> devices = new ArrayList<Device>(row+10);
rs.beforeFirst();
Device device;
//while循环里面非常慢,前面执行都很快
while (rs.next()) {
device = new Device();
device.setUdid(rs.getString("udid"));
device.setCountry(rs.getString("country"));
device.setLanguage(rs.getString("language"));
device.setOsVersion(rs.getString("osVersion"));
device.setPlatform(rs.getInt("platform"));
device.setToken(rs.getString("token"));
devices.add(device);
}
return devices;
}

#5


new 对象的方式,肯定慢的

#6


引用 5 楼 shijing266 的回复:
new 对象的方式,肯定慢的

new一个对象不慢的,经测试new100W个Device对象非常快的,我觉得问题的瓶颈是ResultSet 遍历这里

#7


为什么要一次查询出这么多的数据呢,这样多占内存,先查出一页再分页展示不行吗?数据库中查询也只是展示了第一页吧。

#8


引用 7 楼 huangan0301 的回复:
为什么要一次查询出这么多的数据呢,这样多占内存,先查出一页再分页展示不行吗?数据库中查询也只是展示了第一页吧。

业务需求,没办法,需要一次性加载到内存中

#9


引用 8 楼 qq467339640 的回复:
Quote: 引用 7 楼 huangan0301 的回复:

为什么要一次查询出这么多的数据呢,这样多占内存,先查出一页再分页展示不行吗?数据库中查询也只是展示了第一页吧。

业务需求,没办法,需要一次性加载到内存中


一次性加载这么多数据到内存!!!!建议你使用文件缓存吧,第一次查询后,把结果集缓存进文件,下次直接读文件
或者使用ehcache做缓存

#10


问题就出现在,你查询出数据再装到java中这个过程中慢,你可以打印一下时间,即每次rs.next()的时间,会发现在把数据装到Java内存里面的时候花费 了大量的时间、
以前做过读取好几G的表,基本要读取一晚上

#11


引用 9 楼 asdf544265772 的回复:
Quote: 引用 8 楼 qq467339640 的回复:

Quote: 引用 7 楼 huangan0301 的回复:

为什么要一次查询出这么多的数据呢,这样多占内存,先查出一页再分页展示不行吗?数据库中查询也只是展示了第一页吧。

业务需求,没办法,需要一次性加载到内存中


一次性加载这么多数据到内存!!!!建议你使用文件缓存吧,第一次查询后,把结果集缓存进文件,下次直接读文件
或者使用ehcache做缓存


引用 10 楼 vtopqx 的回复:
问题就出现在,你查询出数据再装到java中这个过程中慢,你可以打印一下时间,即每次rs.next()的时间,会发现在把数据装到Java内存里面的时候花费 了大量的时间、
以前做过读取好几G的表,基本要读取一晚上

的确就是问题出现在rs.next():没办法了,重新换了数据库,没用mysql,改用mongodb了,百万级数据到内存中也就5-6s这个可以接受了,谢谢各位的回答

#12


引用 9 楼 asdf544265772 的回复:
Quote: 引用 8 楼 qq467339640 的回复:

Quote: 引用 7 楼 huangan0301 的回复:

为什么要一次查询出这么多的数据呢,这样多占内存,先查出一页再分页展示不行吗?数据库中查询也只是展示了第一页吧。

业务需求,没办法,需要一次性加载到内存中


一次性加载这么多数据到内存!!!!建议你使用文件缓存吧,第一次查询后,把结果集缓存进文件,下次直接读文件
或者使用ehcache做缓存

缓存没多大用,数据库里面的数据更新比较频繁的