分片+异步 优化in子查询

将一次性查询改为通过分片、异步优化 in子查询

集合数据分片是将数据按指定大小进行分组,像java中使用guava或hutool工具的partition进行分组,然后分批处理或者获取数据,in子查询会通过创建临时表,不易将大量数据放入in子查询中

案例:分片+异步操作

@Test
void test32() {

    ExecutorService orderExecutorService = Executors.newFixedThreadPool(10);

    List<Integer> userIds = new CopyOnWriteArrayList<>();
    userIds.add(1);
    userIds.add(2);
    userIds.add(3);
    userIds.add(4);
    userIds.add(5);
    List<List<Integer>> partitionUserIds = ListUtil.partition(userIds, 2);

    final List<Object> allOrders = new ArrayList<>(partitionUserIds.size());

    // 分片+异步
    partitionUserIds.stream().map(item -> {
        return CompletableFuture.runAsync(() -> {
            // 查询数据库并添加到集合中
            ArrayList<Object> data = new ArrayList<>();
            allOrders.addAll(data);
        }, orderExecutorService);
    }).collect(Collectors.toList()).forEach(CompletableFuture::join);

    // 执行业务操作
    allOrders.forEach(System.out::println);

}

分片实现原理

/**
 * 集合分片处理
 *
 * @param datas 需要分片的集合
 * @param limit 一个分片大小
 * @param <T>
 * @return
 */
public static <T> List<List<T>> toPart(List<T> datas, int limit) {

    if (datas == null || datas.size() == 0) {
        throw new RuntimeException("数据不能为空");
    }
    int size = datas.size();
    if (size <= limit) {
        return Collections.singletonList(datas);
    }

    List<List<T>> partsList = new ArrayList<>();
    // 已经查询的条数
    int passIndex = 0;
    do {
        int endIndex = Math.min(passIndex + limit, size);
        // 注意subList是前闭后开,开始索引与结束索引不能一样
        List<T> currPartList = datas.subList(passIndex, endIndex);
        partsList.add(currPartList);
        passIndex = endIndex;
    } while (passIndex < size);

    return partsList;
}

@Test
public void test23() {
    List<Integer> nums = new ArrayList<>(5);
    for (int i = 0; i < 5; i++) {
        nums.add(i);
    }
    toPart(nums, 3).forEach(System.out::println);
}

自动分页查询

@Test
public void selectBatch() {
    // 1.查询总条数
    int total = 5;

    // 每次查询条数
    int limit = 2;
    // 已经查询的条数
    int offset = 0;
    do {
        System.out.println("select * from a limit " + offset + "," + limit);
        offset = limit + offset;
    } while (offset <= total);
}
posted @ 2023-09-02 12:11  永无八哥  阅读(34)  评论(0编辑  收藏  举报