SpringBoot Mybatis 数据库流式读取优化。

     众所周知的,Mybatis作为一个优秀的ORM框架极大方便了我们对数据库CUID的操作,但是Mybatis对底层JDBC的封装同时也给我们底层调优带来了一些问题,例如前段时间,存在一个这样的业务场景,如果要从数据库当中读取 1000W 条数据来进行处理。也许我们都会考虑采用select limit之类的语句来分批处理,这不乏为一个较好的解决方案。但是我们更期望对读取的数据逐行处理(即流式处理)。这个时候JDBC可能采用返回游标的方式就可以完成。Oracle和MySQL在服务器端已经帮我们完成游标偏移,这样也使得客户端可以用较少内存来处理数据库返回的数据。废话不多说了,接下来我展示两个例子。

   (1)数据库中存了100W个账号,我们需要读取出来并处理,采用Mybatis全量读出并处理方案。代码如下:

//DAO层
public interface DataMapper {
	//void getHSUser();
	List getAllUsers();
}

映射XML文件

	
	
		 
	


		


运行结果,启动虚拟机,限制参数为:-Xms12m -Xmx12m 堆参数,发现运行2分钟之内,内存即崩溃,此外CPU使用率持续在 50% GC回收跟不上。

java.lang.OutOfMemoryError: GC overhead limit exceeded
at org.apache.ibatis.reflection.factory.DefaultObjectFactory.instantiateClass(DefaultObjectFactory.java:62) ~[mybatis-3.4.5.jar:3.4.5]

at org.apache.ibatis.reflection.factory.DefaultObjectFactory.create(DefaultObjectFactory.java:50) ~[mybatis-3.4.5.jar:3.4.5]

接下来我展示一个流式的处理手段

首先定义数据库配置

@Configuration
@MapperScan(basePackages = "ems.rm.datasourceservice", sqlSessionFactoryRef = "hsdataSqlSessionFactory")
public class DataConfig {

		@Bean(name = "HSDataSource")
		@ConfigurationProperties(prefix = "spring.datasource.hsdata")
		@Primary
		public DataSource dataSource() {
			return DataSourceBuilder.create().build();
		}

		@Bean(name = "hsdataSqlSessionFactory")
		@Primary
		public SqlSessionFactory  sqlSessionFactory(@Qualifier("HSDataSource") DataSource dataSource)
				throws Exception {
			SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
			bean.setDataSource(dataSource);
			bean.setMapperLocations(
					new PathMatchingResourcePatternResolver().getResources("classpath:mybatis/hsMapper.xml"));
			return bean.getObject();
		}


		@Bean(name = "hsdataTransactionManager")
		@Primary
		public DataSourceTransactionManager transactionManager(@Qualifier("HSDataSource") DataSource dataSource) {
			return new DataSourceTransactionManager(dataSource);
		}

		@Bean(name = "hsdataSqlSessionTemplate")
		@Primary
		public SqlSessionTemplate sqlSessionTemplate(
				@Qualifier("hsdataSqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception {
			return new SqlSessionTemplate(sqlSessionFactory);
		}
}

DAO层

public interface DataMapper {
	void getHSUser();
}


服务层访问代码

@Service
public class DataService {
	@Autowired
	SqlSessionTemplate template;
	

	
	@SuppressWarnings("rawtypes")
	@Scheduled(fixedRateString ="${ems.rm.cpyalgorithm.alarmCheck}")
	void TestFunc()
	{

		template.select("ems.rm.datasourceservice.HSDataMapper.getHSUser",
				new ResultHandler() {

            @Override
            public void handleResult(ResultContext resultContext) {
            	HsUser hsUser = (HsUser) resultContext.getResultObject();
                //System.out.println(resultContext.getResultCount());
                System.out.println(hsUser);
            }
		});
	}
}

XML配置

  

	
	
		 
	

		



     重点讲解下红色代码,既然直接访问会造成内存过大,GC回收过于缓慢,那么我们采用红色方式,即可完成游标窗口的访问形式,Mybatis提供了回调ResultHandler方式可以完成数据逐条访问,这种方式在大数据量场景非常有用,可以均衡系统复杂性和系统资源占用两个因素。

运行结果,启动虚拟机,限制参数为:-Xms12m -Xmx12m 堆参数,程序即可稳定运行,CPU使用率持续在 10%左右稳定。





你可能感兴趣的:(Java,Mybatis,性能调优)