用 Spring AOP 优化 IN 查询
SELECT * FROM device WHERE id IN (1, 2, 3, 4)
拆分为
SELECT * FROM device WHERE id IN (1, 2) SELECT * FROM device WHERE id IN (3, 4)
结合SpringAOP写了一个基于注解优化方案,只需要打上注解就可以提升性能了。实现效果以及具体实现逻辑如下:
@SplitWorkAnnotation(setThreadPool = LIST_DEVICE_EXECUTOR, splitLimit = 20, splitGroupNum = 10)
public listDeviceDetail(Long projectId,@NeedSplitParam List<Long> deviceId){
......
}
使用场景=====
fun(a,b,bigList) = fun(a,b,bigListPart1) + fun(a,b,bigListPart2)
定义AOP注解
需要定义的注解参数:
- setThreadPool: 线程池,可能阻塞比较大,不要用公共的线程池最好自己定义一个
- handlerReturnClass: 返回值回调函数,对应不同返回值处理逻辑:可能是合并可能取前十条可能求和
- splitLimit: 超过多少需要拆分
- splitGroupNum: 拆分时每组多少个
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface SplitWorkAnnotation {
/**
* 设置线程池
*
* @return {@link ThreadPoolEnum}
*/
ThreadPoolEnum setThreadPool();
/**
* 返回值处理
*
* @return {@link Class}<{@link ?} {@link extends} {@link HandleReturn}>
*/
Class<? extends HandleReturn> handlerReturnClass() default MergeFunction.class;
/**
* 超过多少开始拆分 >
*
* @return int
*/
int splitLimit() default 1000;
/**
* 拆分后每组多少
*
* @return int
*/
int splitGroupNum() default 100;
}
标记需要拆分参数的注解
加在需要拆分的参数上,只支持一个。因为两两组合情况非常复杂,也一般不符合实际使用情况。
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.PARAMETER)
public @interface NeedSplitParam {
}