【发布时间】:2017-10-06 15:31:00
【问题描述】:
在一个遗留项目中尝试优化 Hibernate 4.2 生成的 MySQ 慢查询时,我发现下面的代码生成了近 500 个 SQL 查询(有很多重复):
class MyDAO {
public List<Message> findMessages() {
Session session = MyHibernateUtils.openSession();
String queryStr = "SELECT DISTINCT m FROM Message m "
+ " LEFT JOIN fetch m.types types "
+ " LEFT JOIN fetch m.mainType mainType "
+ " LEFT JOIN fetch m.place place "
+ " LEFT JOIN fetch m.building building "
+ " LEFT JOIN fetch m.city city "
+ " LEFT JOIN fetch m.kind kind "
+ " LEFT JOIN fetch m.domain domain "
+ " LEFT JOIN fetch m.action action "
+ " LEFT JOIN fetch m.customParameterA customParameterA "
+ " LEFT JOIN fetch m.customParameterB customParameterB "
+ " LEFT JOIN fetch m.scheduleEvents scheduleEvents "
+ " LEFT JOIN fetch m.comments comments "
+ " LEFT JOIN fetch m.messageLastActivities messageLastActivities "
+ " LEFT JOIN fetch m.customListA customListA "
+ " LEFT JOIN fetch m.childEvents childEvents "
+ " LEFT JOIN fetch m.parentEvent parentEvent "
+ " WHERE ...";
List<Message> messages;
try {
session.getTransaction().begin();
Query query = session.createQuery(queryStr);
query.setTimeout(10);
messages = query.list();
session.getTransaction().commit();
} catch (RuntimeException e) {
session.getTransaction().rollback();
throw e;
} finally {
session.close();
}
return messages;
}
}
我怎样才能避免有这么多的 SQL 查询?
我不知道它是否有帮助,但实体之间有很多 onyToMany 和 manyToMany 关系。
感谢您的帮助。
【问题讨论】:
-
ORM 框架大部分时间都是这样工作的......他们需要额外触发一个
SELECT * FROM table WHERE id = 1来查找相关实体 -
@RaymondNijland 不,他们没有。好吧,在最坏的情况下,他们会这样做,但大多数时候这是可以避免的,当然在 Hibernate 中也是如此。只有非常幼稚的 ORM 才会这样做,因为它会降低性能并使框架变得毫无价值。
-
至于 OP,为 Hibernate 启用 SQL 日志记录(环顾四周,我不记得它是如何完成的)并查看执行了 what 查询.这将允许您查明原因,这可能只是您需要修复的单个 N+1 查询。
-
真@Kayaman ..
-
@Kayaman 是的,他们这样做了,而且 raymond 是对的。 Eagar 提取通常需要额外的操作(如添加注释或连接)