能否解决一下著名的N+1性能问题
问题描述 目前对于有一对多关系的关联查询,如下,会存在著名的N+1问题,这个在Hibernate、graphql中都是重点问题,希望能解决一下。
{
"[]":{ //请求一个数组
"page":0, //数组条件
"count":5,
"Moment":{ //请求一个名为Moment的对象
},
"User":{
"id@":"/Moment/userId", //User.id = Moment.userId 缺省引用赋值路径,从所处容器的父容器路径开始
},
"Comment[]":{ //请求一个名为Comment的数组,并去除Comment包装
"count":2,
"Comment":{
"momentId@":"[]/Moment/id" //Comment.momentId = Moment.id 完整引用赋值路径
}
}
}
}
这里查询Moment列表,带出User和CommentList时都是查询了N遍,希望能优化一下 目前通过app join可以解决一对一的情况,一对多还是不行的。
这里和 Moment 写在同一层级的 User 可以用 APP JOIN/LEFT JOIN 优化 "join": "@/User/id@" // APP JOIN,两条 SQL,副表 User WHERE id IN(主表 Moment.userId 集合) "join": "</User/id@" // LEFT JOIN,一套 SQL,Moment LEFT JOIN User ON User.id = Moment.userId
https://github.com/Tencent/APIJSON/blob/master/Document.md#3.2
后续 APP JOIN 将支持跨层级,感谢建议~
APIAuto 上有关于 APIJSON 各种零代码 JOIN 的例子
http://apijson.cn/api/

视频 https://www.bilibili.com/video/BV1LU4y157eP
APP JOIN 文档:
https://github.com/Tencent/APIJSON/blob/master/Document.md#32-%E5%8A%9F%E8%83%BD%E7%AC%A6

如果 APP JOIN 要支持一对多的写法,可以在 AbstractParser.onJoinParse 内判断 isAppJoin(join 值以 "@/" 开头),这种情况下允许写成
"@/ViceTable[]/ViceTable" 或 "@/ViceTable[]/ViceTable/key@" 这两种形式,相比原来仅支持的一对一写法
"@/ViceTable" 和 "@/ViceTable/key@",一对多中间多了数组名 ViceTable[]。
https://github.com/Tencent/APIJSON/blob/master/APIJSONORM/src/main/java/apijson/orm/AbstractParser.java#L1449-L1480

这个数量 1 目前是按一对一设置的,适配一对多需要在 AbstractParser.onJoinParse 把副表数组内的 count 取出来(没有就用默认值)存到 Join 内属性, https://github.com/Tencent/APIJSON/blob/master/APIJSONORM/src/main/java/apijson/orm/AbstractParser.java#L1576-L1649

然后这里给 cacheConfig 设置进去
https://github.com/Tencent/APIJSON/blob/master/APIJSONORM/src/main/java/apijson/orm/AbstractSQLConfig.java#L5010-L5011

可以先按以上方式验证 APP JOIN 是否能按一对多结构返回副表数据,且手动传参 count:1 时查副表数组应该走缓存。 此时副表数组内只返回一个值,没其它问题的话再改 setCount。
@StickChen APIJSON 5.1.5 已支持跨层级 APP JOIN。
跨级 APP JOIN;腾讯业务百万数据 6s 响应
https://github.com/Tencent/APIJSON/releases/tag/5.1.5

目前最新版是 5.3.0。 APIJSON 5.3.0 支持达梦数据库,新进腾讯前 9 开源项目 https://www.oschina.net/news/214851/apijson-5-3-released