表中有超过10,00,000条记录,我正在努力。我需要为每条记录执行异步操作(推送队列)。一次获取所有记录并在循环中处理每个记录感觉就像一个坏主意。相反,我想分批获取记录并循环遍历每个批次。在互联网上阅读有关使用setFetchSize(int n)批量查询的内容,我的DAO看起来像:
public List<UserPreferenceDTO> getUserPreferences() {
String sqlQueryString = "select us.id as userId, pf.id as preferenceId from users us, preferences pf where us.id = pf.user_id;";
SQLQuery sqlQuery = (SQLQuery) session.createSQLQuery(sqlQueryString).setFetchSize(200);
return sqlQuery.addScalar("userId").addScalar("preferenceId").setResultTransformer(new AliasToBeanResultTransformer(UserPreferenceDTO.class)).list();
}
我的服务类如下:
List<UserPreferenceDTO> userPreferenceDTOs = userDeviceDao.getUserPreferences();
for(UserPreferenceDTO userPreferenceDTO: userPreferenceDTOs ){
pushToRabbitMQ(userPreferenceDTO);
}
我需要得到&#34; N&#34;来自数据库的记录将它们推送到队列进行处理然后得到另一个&#34; N&#34;记录将它们推送到队列中,依此类推,直到所有记录都被推送到队列中。
答案 0 :(得分:0)
在任何批量加载方案中都必须使用合理的setFetchSize()
,因为数据库不必单独发送每一行。即使您到数据库的往返只是10ms
,它仍然10ms * 10mln ~ 28 h
为所有行执行此操作。这种改进通常在1000左右的平稳处,但这取决于您的环境设置,因此您需要对其进行测试。
将.list()
替换为.scroll()
可能就足够了,ScrollableResults
返回ORDER BY
,允许一次读取一条记录。然而,这将取决于数据库,有些像MySQL will fake the scrolling and load the entire result set。
如果是这种情况,您需要在setFirstResult()
和setMaxResult()
的查询中使用ORDER BY
。这将执行新查询以读取每个批次。这是最安全的方法,但trackedinfo
可能是一个昂贵的陈述。