如何批量选择所有表记录并处理每批。

时间:2018-04-05 16:02:06

标签: java postgresql hibernate

表中有超过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;记录将它们推送到队列中,依此类推,直到所有记录都被推送到队列中。

1 个答案:

答案 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可能是一个昂贵的陈述。