手机登录网站怎么建设,网页制作软件免费版,建立网站免费,在线生成电子印章优化场景描述
当时是测试环境#xff0c;进行一个列表的初始化分页查询#xff0c;pageSize 为8#xff08;已经很小了#xff09;#xff0c;页面的数据项也很少#xff0c;就那么几个信息#xff0c;但是性能压测通过不了。
提出性能问题假设
事关性能问题#xf…优化场景描述
当时是测试环境进行一个列表的初始化分页查询pageSize 为8已经很小了页面的数据项也很少就那么几个信息但是性能压测通过不了。
提出性能问题假设
事关性能问题我们不妨大胆的假设
pageSize只有8会不会是返回的数据包含的信息量太大网络IO顶不住接口会不会有第三方的调用有等待延迟接口内部的查询逻辑会不会过于复杂需要多表且多次查询数据库数据量太大查询是否命中索引或是否需要索引查询的SQL语句是否有不合理需要优化的地方
按假设逐一排查
1、pageSize只有8会不会是返回的数据包含的信息量太大网络IO顶不住
在查询页面打开F12查看接口的返回数据不难发现返回的List列表里面层层嵌套了不少List列表案例只嵌套了一层不过有3个嵌套且嵌套在内部的数据量还不小。
结论有可能是信息量太大。
2、接口会不会有第三方的调用有等待延迟
进入接口内部没有发现第三方的调用就不存在等待延迟。
结论排除可能。
3、接口内部的查询逻辑会不会过于复杂需要多表且多次查询
进入接口内部逻辑很清晰就是一个单表的分页查询。
结论排除可能。
4、数据库数据量太大查询是否命中索引或是否需要索引
测试环境的数据量算很小了索引不索引的不应该是影响性能的主要原因。
结论排除可能。
5、查询的SQL语句是否有不合理需要优化的地方
接口采用的Spring Data JPA 的findAll 分页查询属于JPA的东西应该不会有太大的性能问题吧。
结论JPA的findAll 查询有可能有性能问题。
那么最有可能的就是1和5了那就进一步排查。
因为返回值存在List的层层嵌套而接口又是一个单表查询这是不是有点矛盾那么朝矛盾点进发打开对应的类对象仔细一看好家伙嵌套的List 对象上各自添加了 OneToMany、ManyToMany、ManyToOne 注解注解让我们查询的表与其他表进行了级联操作。findAll 方法会去查询关联表的信息。3个级联关系再查询3次SQL性能差距也不能这么差吧。于是我再去看findAll 方法执行时的日志不看不知道一看吓一跳。findAll 方法执行了很多次的查询经我观察发现关联表相关的数据量越大查询的次数就越多根源问题找到了SQL的多次执行。
结论因为对象的级联关系导致 findAll 会自动查询关联表多次查询的信息并进行数据封装导致数据库压力大造成性能问题。
优化分析 从业务需求方面 是否需要级联查询的关联数据如果不需要去掉级联查询。 从网络IO方面 返回的冗余数据量过多需要剔除冗余数据量。 从SQL方面 发现findAll 方法会因为关联数据增多而新增查询语句导致多次查询。因此决定自行写SQL。 从缓存方面 如果没有冗余数据也采用了SQL优化的方法但还是慢则要考虑redis缓存了。
解决措施 从业务需求方面 List的嵌套数据确实是多余的可以去掉级联查询到的多余List。 从网络IO方面 返回值对象重新封装一下只返回需要返回的数据。 从SQL方面分页查询返回的Page 采用 nativeQuery true 自行编写sql的方式但是不能返回 Page这样会触发级联查询。因此用 PageMapString, Object 对象接受查询的返回值跟踪日志发现接口查询只进行了一次SQL查询并做map 的List处理 用JSON.parseArray(JSON.toJSONString(List对象), 类对象名.class) 处理得到想要的List对象。
小结当类对象存在 OneToMany、ManyToMany、ManyToOne 等注解时要特别注意findAll(Nullable Specification var1, Pageable var2) 返回的 Page T 会自行进行级联查询并数据封装。使用自定义的查询nativeQuery true并返回 PageMapString, Object 对象就可以避免级联查询。