数据库查询——性能调优~
本帖最后由 niushuai666 于 2013-12-06 16:26:19 编辑 现在项目出现了一个性能瓶颈:
我有A/B/C,3个表
现在通过B查询状态为1的记录,大概4000条。然后遍历这4000条:
在C表(50万记录)查找id和B表id相同的记录
所以,性能瓶颈就是C表根据id查询。所以需要执行4000次查询。再包括建立连接、断开连接之类的开销。现在完成这个模块大概需要4分钟左右。
我现在想优化的思路是这样:
通过1次查询把C表的信息全部读进内存。但是问题是,如果我没有任何处理就读取,那么返回的是List<Object>对象,我需要完成4000 * 50万遍历才能完成这个任务。这样就更悲剧了。 所以,我想
select * from C where id in (1,2,3,4,5,...4000); 然后把这些结果装到一个
HashMap<B表id, List<Object>>。这样我用到的时候根据id就可以拿。
不知道SimpleJdbcTemplate有这样的函数吗????在线急等~~~
[解决办法]
如果C表数据不怎么变化的话,可以考虑服务启动时,做个将C表加载到内存的任务,数据结构使用HashMap<B表id, List<Object>>,用的时候直接map.get(B表id)。
C表数据发生变化时,内存里的map对应的id对应的list也相应进行更新。
这要考虑内存,如果C表字段比较多,可能会占用很大内存。如果有条件,可以搞个缓存服务器。
[解决办法]
SimpleJdbcTemplate不是有queryForObject(String sql,RowMapper rowMapper,Ojbect... args)方法吗这个方法就是返回你rowMapper的mapRow方法所返回的对象所以楼主只要利用BeanPropertyRowMapper进行属性和数据库字段的自动映射
Map<Integer,List<C>> map=new HashMap<Integer,List<C>>();
(Map<Integer,List<C>>)simpleJdbcTemplate.queryForObject(sql,new BeanPropertyRowMapper(C.class){
//这里重写下rowMapper方法把获得的C对象放到map中就是了
public Object mapRow(ResultSet rs,int rowNum){
//原来的方法就是会返回c对象了
C c=(C)super.mapRow(rs,rowNum);
//接下来只需要把这个c对象放到map中返回map即可
Integer id=c.getId();
List<C> list=map.get(id);
if(list==null){
list=new ArrayList<C>();
map.put(list);
}
list.add(c);
return map;
}
},args)
Select *
From c Join b On c.id = b.id
Where b.state=1