Java Hibernate 复杂实体关联下,简单查询都很慢,如何优化?

325 天前
 XiaoJiang9527

最近正在整改一个老项目,里面的表结构错综复杂,实体中的映射表字段基本都增加了 @ManyToOne 和 @JoinColumn 注解,导致很多简单单表查询都需要执行很久。 但是打印具体 hibernate SQL 日志,Explain 下,也不存在什么性能问题,各位大佬们,怎么解?

5727 次点击
所在节点    程序员
65 条回复
Nosub
324 天前
nothingistrue
324 天前
@Nosub #40 JPA 是标准,Hibernate 是一种实现 ,Spirng Data JPA 跟 Hibernate 就是 Spring Boot 跟 Spring 的关系。你这来源是瞎比较,你不能下。
dog82
324 天前
实在不行就上物化视图,用空间换时间
Nosub
324 天前
@nothingistrue Hibernate 的开发团队写的,瞎在哪儿。
nothingistrue
324 天前
@Nosub #41 上原文链接
XiaoJiang9527
324 天前
@dog82 准备重新提炼业务,切换实现方案,因为目前数据量不是很大,先用 SQL 开路解决
zhazi
324 天前
水平差,冤框架。让上代码也不上,block
Nosub
324 天前
@nothingistrue 你可以看看《 Java Persistence with Hibernate Second Edition 》,数据来自这本书,作者你也可以看看。
XiaoJiang9527
324 天前
@Nosub 好的,感谢
forbreak
324 天前
说 hibernate 慢的,都是不愿意学高级用法。埋头狂写,能不慢吗。
wangYQ
324 天前
@XiaoJiang9527 但是这样的成本有点大,
1.老项目,其中业务饱经沧桑,如果有很熟悉业务的完全可以重新改,如果不存在业务完全了解的人,还是不要贸然干,不知道有什么特殊业务的坑藏在细小的地方。
2.SQL 单独执行很快,只是关联查询慢,看能不能把需要的数据通过数据库层面视图,冗余字段,减少一个接口调用太多的 SQL ,减少开销。
3.如果项目后期有更换数据库的需求,Hibernate ,JPA 这种还算是比较方便,换个方言能解决一大部分的事情,要是都是原生 SQL 用了一些特殊函数,改数据库的话工作量特别大
XiaoJiang9527
324 天前
@wangYQ 是的,目前真是没办法下手。
目前我对项目的选型和方案制定倒是没有很大的敌意,仅想寻找一种合适的解决方案。
上面大佬的那些方案目前正在一个个尝试。
nothingistrue
324 天前
@Nosub #45 这本书是付费书籍,你这又连完整原文截图都没有,你这是在自认「断章取义」,还是在自认「没看原文而是看了某人的断章取义」。

这个图应该是真的,但是它需要结合完整原文才能知道说得是什么。这里比较的很可能是,「直接用 Hibernate 的 API 」、「用 JDK 的 JPA 」 、用「 Spring Data JPA 」 ,这三种,使用 Hibernate 的途径的性能。 三个都是 Hibernate ,只不过使用方式不同。
iyiluo
324 天前
屎山项目,除非整个模块重构,任何试图在旧代码上优化的行为都是往屎山上拉屎
wangYQ
324 天前
@XiaoJiang9527 不能抱有敌意,根据对技术喜好看问题。如果你换成 mybatis 也会面临其他的问题,也没有办法保证百分百没有其他的问题。在有限的空间内做最大程度的优化就好,即使就是搞不定了,需要重构,也是需要多人讨论,评审后,再下结论,做选型,做改造。说句不好听的话,接手了屎山,改造就好比屎山雕花,有时候盲目的重构,弄完发现不过是在屎山旁边又拉了一坨。
XiaoJiang9527
324 天前
@iyiluo 嗯,确实烂的一塌糊涂
XiaoJiang9527
324 天前
@wangYQ 没错,这种工作吃力不讨好的,没有一种方案是能够保证百分百解决的。
yidinghe
324 天前
Hibernate 的初衷就是想偷懒,想回避关系数据库,结果到了最后,发现在 Hibernate 体系里面学那么多、写那么多,依旧耗费大量精力,而且还不如一条手写 SQL 搞定。

Nosub
324 天前
给 OP 提供一个解决方案,比如有个文章表,和一个 User 表,我要查询所有文章列表,文章列表又要返回这篇文章的作者信息,我这里写了一个投影和一个 DTO ,用 nativeQuery 方式查询。

@Data
@AllArgsConstructor
@NoArgsConstructor
public class UserInfoDto {
private Long id;
private String name;
private String avatar;
}

public interface PostInfo {
long getCreateTime();
long getModifiedTime();
Long getId();
String getTitle();
String getSummary();
String getContent();
@Value("#{new com.momo.xxx.dto.UserInfoDto(target.user_id, target.user_name, target.user_avatar)}")
UserInfoDto getAuthor();
}


user_info 表示用户表,Post 表示文章列表。

@Query(value = "SELECT p.id,user_info.id AS user_id, user_info.name AS user_name, user_info.avatar AS user_avatar,p.title,p.summary,p.CONTENT,p.state,p.create_time AS createTime,p.modified_time AS modifiedTime FROM Post p JOIN user_info ON user_info.id=p.author_id WHERE p.is_delete = FALSE AND p.STATE = 5 ORDER BY p.ID DESC",
nativeQuery = true)
Page<PostInfo> findAllPublishedPostsNative(Pageable pageable);

如果直接用 Spring Data Jpa 查询 10 条数据大概要 4192ms ,可能更慢,用 Native 方式可能只要 130ms ,这个数据只是我的一个测试数据;
TGhoull
323 天前
@UBcai 你应该这么想想,Hibernate 要是如你所说的那么拉,它还能在国外称霸那么多年吗?

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/1013581

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX