背景
- 在实际的项目开发中,我们经常需要通过某个关联去数据库查询相关的记录。
- 如果是前端带分页的接口还好,但是也要考虑深度分页带来的问题。
- 而更多的有时候没有预估到生产的数据量,导致单次查询量太大把程序打到OOM。
问题
- 笔者在查看生产日志时,发现有个带条件的查询返回了70W+的记录,导致mybaits直接OOM。
- 相关逻辑是根据一个父ID去查询全部子记录,之后遍历子记录进行相关的业务逻辑操作
相关代码
import org.apache.ibatis.annotations.Options;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.mapping.ResultSetType;
public interface xxxDao extends BaseDao{
#根据父appId查询子记录,使用Options注解来标记是游标查询,每次查询10000条
@Options(resultSetType = ResultSetType.FORWARD_ONLY, fetchSize = 10000)
List<xxxBean> selectByAppId(@Param("appId") Long appId);
}
import org.apache.ibatis.cursor.Cursor;
import org.apache.ibatis.session.SqlSession;
import org.mybatis.spring.SqlSessionTemplate;
@Autowired
private SqlSessionTemplate sqlSessionTemplate;
public void test1() throws IOException {
List<xxxBean> list= new ArrayList<>();
SqlSession sqlSession =sqlSessionTemplate.getSqlSessionFactory().openSession();
//90137L表示查询的参数
Cursor<HdfsPathRecord> cursor = sqlSession.selectCursor(xxxDao.class.getName() + ".selectByAppId",90137L);
Iterator iter = cursor.iterator();
while (iter.hasNext()) {
xxxBean obj = (xxxBean) iter.next();
//TODO:接下来可以根据obj执行实际逻辑或者将obj放到一个list中
}
cursor.close();
sqlSession.close();
}
网友评论