【问题标题】:How to select all the table records in batches and process each batch.?如何批量选择所有表记录并处理每个批次。?
【发布时间】:2018-04-05 16:02:06
【问题描述】:

表中有超过 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);
    }

我需要从数据库中获取“N”条记录将它们推送到队列中进行处理,然后再获取另外“N”条记录将它们推送到队列中,依此类推,直到所有记录都推送到队列中。

【问题讨论】:

    标签: java postgresql hibernate


    【解决方案1】:

    合理的setFetchSize() 在任何批量加载场景中都是必须的,因为数据库不必单独发送每一行。即使您到数据库的往返只是10ms,它仍然是10ms * 10mln ~ 28 h 为所有行执行此操作。改进通常在 1000 左右达到稳定水平,但这取决于您的环境设置,因此您需要对其进行测试。

    .list() 替换为.scroll() 可能就足够了,ScrollableResults 允许一次读取一条记录。然而,这将取决于数据库,如 MySQL will fake the scrolling and load the entire result set

    如果是这种情况,您需要在查询中使用ORDER BYsetFirstResult()setMaxResult()。这将执行新查询以读取每个批次。这是最安全的方法,但ORDER BY 可能是一个昂贵的声明。

    【讨论】:

    猜你喜欢
    • 2020-02-12
    • 1970-01-01
    • 2017-01-11
    • 1970-01-01
    • 1970-01-01
    • 2013-03-17
    • 1970-01-01
    • 2021-09-20
    • 2023-03-02
    相关资源
    最近更新 更多