Java HIbernate条件查询深度联接的性能问题
我面临涉及深度联接的hibernate条件查询的性能问题。 当我在数据库中直接执行hibernate生成的查询时,结果会在几秒钟内返回。 通过hibernate,它需要一些与结果大小成指数关系的时间。如果有10个结果,则需要1秒。如果有大约500个结果,那么它会持续15秒,如果超过1000个,那么它会持续30秒,就像这样 下面是hibernate生成的查询和我正在使用的Java代码。在下面的日志中,您可以看到打印查询后,30秒后返回结果。 我在hibernate中使用元组查询,并使用结果转换器将结果映射到DTO。 Hibernate版本是5.3.7 我已经启用了hibernate调试来获取一些详细信息,并且hibernate在结果集中循环的时间如下所述。 6465条记录被获取,我认为hibernate需要将近30秒的时间循环遍历每个结果集。 这正常吗 我已将下面的实际表名替换为虚拟表名,因为这是客户机代码的一部分 生成的查询Java HIbernate条件查询深度联接的性能问题,java,hibernate,join,Java,Hibernate,Join,我面临涉及深度联接的hibernate条件查询的性能问题。 当我在数据库中直接执行hibernate生成的查询时,结果会在几秒钟内返回。 通过hibernate,它需要一些与结果大小成指数关系的时间。如果有10个结果,则需要1秒。如果有大约500个结果,那么它会持续15秒,如果超过1000个,那么它会持续30秒,就像这样 下面是hibernate生成的查询和我正在使用的Java代码。在下面的日志中,您可以看到打印查询后,30秒后返回结果。 我在hibernate中使用元组查询,并使用结果转换器将
12:12:25.644 INFO query starts at Thu Apr 15 12:12:25 CEST 2021
Hibernate:
select
table1_."table1_id" as col_0_0_,
table4_."table4_id" as col_1_0_,
table5_."table5_id" as col_2_0_,
table5_."table5_col3" as col_3_0_,
table5_."table5_col4" as col_4_0_,
table6_."table6_id" as col_5_0_,
table6_."table6_col6" as col_6_0_,
table6_."table6_col7" as col_7_0_,
table7_."table7_col8" as col_8_0_,
table7_."table7_col9" as col_9_0_,
table7_."table7_col10" as col_10_0_
from
"TABLE_1" table1_
inner join
"TABLE_2" table2_
on table1_."table1_id"=table2_."table1_id"
inner join
"TABLE_3" table3_
on table2_."table3_id"=table3_."table3_id"
inner join
"TABLE_4" table4_
on table3_."table3_id"=table4_."table3_id"
inner join
"TABLE_5" table5_
on table4_."table5_id"=table5_."table5_id"
inner join
"TABLE_6" table6_
on table4_."table4_id"=table6_."table4_id"
inner join
"TABLE_7" table7_
on table6_."table7_id"=table7_."table7_id"
where
table1_."CREATION_DATE">?
and table1_."CREATION_DATE"<?
and (
table1_."col1" is not null
)
and (
table1_."col2" is not null
)
and (
table4_."col1" is null
)
and table1_."col2"=?
12:12:55.741 INFO Total time taken for querying 30 Seconds
12:12:55.743 INFO total size: 2023
Java代码
CriteriaBuilder builder = getCurrentSession().getCriteriaBuilder();
CriteriaQuery<Tuple> criteriaQuery = builder.createTupleQuery();
Root<Table1> root = criteriaQuery.from(Table1.class);
Join<Table1, Table3> table3Join = root.join("table3s", JoinType.INNER);
Join<Table3, Table4> table4Join = table3Join.join("table4s", JoinType.INNER);
Join<Table4, Table5> table5Join = table4Join.join("table5", JoinType.INNER);
Join<Table4, Table6> table6Join = table4Join.join("table6s", JoinType.INNER);
Join<Table6, Table7> table7Join = table6Join.join("table5", JoinType.INNER);
ParameterExpression<Date> startDateParamBuilder = builder.parameter(Date.class);
ParameterExpression<Date> endDateParamBuilder = builder.parameter(Date.class);
ParameterExpression<Boolean> col3ParamBuilder = builder.parameter(Boolean.class);
List<Predicate> conditions = new ArrayList<>();
conditions.add(builder.greaterThan(root.get("creationDate"), startDateParamBuilder));
conditions.add(builder.lessThan(root.get("creationDate"), endDateParamBuilder));
conditions.add(builder.isNotNull(root.get("condition1")));
conditions.add(builder.isNotNull(root.get("condition2")));
conditions.add(builder.isNull(table4Join.get("condition3")));
criteriaQuery
.multiselect(
root.get("id"),
table4Join.get("id"),
table5Join.get("id"),
table5Join.get("col3"),
table5Join.get("col4"),
table6Join.get("id"),
table6Join.get("col6"),
table6Join.get("col7"),
table7Join.get("col8"),
table7Join.get("col9"),
table7Join.get("col10"))
.where(conditions.toArray(new Predicate[0]));
Query query = getCurrentSession().createQuery(criteriaQuery);
query.setParameter(startDateParamBuilder, startDate);
query.setParameter(endDateParamBuilder, endDate);
Table1SearchResultTransformer Table1SearchResultTransformer = new Table1SearchResultTransformer();
query.unwrap(org.hibernate.query.Query.class).setResultTransformer(Table1SearchResultTransformer).getResultList();
CriteriaBuilder=getCurrentSession().getCriteriaBuilder();
CriteriaQuery CriteriaQuery=builder.createTupleQuery();
Root=criteriaQuery.from(表1.class);
Join table3Join=root.Join(“table3s”,JoinType.INNER);
Join table4Join=table3Join.Join(“table4s”,JoinType.INNER);
Join table5Join=table4Join.Join(“table5”,JoinType.INNER);
Join table6Join=table4Join.Join(“table6s”,JoinType.INNER);
Join table7Join=table6Join.Join(“table5”,JoinType.INNER);
ParameterExpression startDateParamBuilder=builder.parameter(Date.class);
ParameterExpression endDateParamBuilder=builder.parameter(Date.class);
ParameterExpression col3ParamBuilder=builder.parameter(Boolean.class);
列表条件=新建ArrayList();
添加(builder.greaterThan(root.get(“creationDate”)、startDateParamBuilder);
add(builder.lessThan(root.get(“creationDate”),endDateParamBuilder));
add(builder.isNotNull(root.get(“条件1”));
add(builder.isNotNull(root.get(“条件2”));
add(builder.isNull(table4Join.get(“条件3”));
标准查询
.多选(
root.get(“id”),
表4join.get(“id”),
表5join.get(“id”),
表5加入。获取(“col3”),
表5加入。获取(“col4”),
表6join.get(“id”),
表6加入。获取(“col6”),
表6加入。获取(“col7”),
表7加入。获取(“col8”),
表7加入。获取(“col9”),
表7join.get(“col10”))
.where(conditions.toArray(新谓词[0]);
Query Query=getCurrentSession().createQuery(criteriaQuery);
setParameter(startDateParamBuilder,startDate);
query.setParameter(endDateParamBuilder,endDate);
Table1SearchResultTransformer Table1SearchResultTransformer=新Table1SearchResultTransformer();
query.unwrap(org.hibernate.query.query.class).setResultTransformer(Table1SearchResultTransformer.getResultList();
我能够解决这个问题。性能问题主要是由于oracle默认获取大小为-10的记录。在我的例子中,这导致了太多的数据库往返,导致了大量的结果
因此,我将fetch大小设置为1000左右,响应时间发生了巨大变化。6000条记录的响应时间现在减少到3秒
query.unwrap(org.hibernate.query.Query.class).setFetchSize(1000)
在这篇文章中有一些关于如何正确使用fetchsize的见解
上述查询是否是唯一执行的查询?如果是这样,这实际上是一个SQL问题。请尝试
EXPLAIN
ing查询,查看我提到的时间在哪里,只有在代码中执行hibernate条件查询时,才会占用该时间。我已经在数据库中检查了直接触发查询的解释计划,这没有问题,结果在毫秒内返回。这不是sql问题。添加了花费所有时间的hibernate调试日志。是否尝试删除Table1SearchResultTransformer
以查看是否存在问题?转换在我之前放置的调试日志(org.hibernate.loader.loader结果行)之后开始。变压器速度很快。100排大约需要20毫秒。
query.unwrap(org.hibernate.query.Query.class).setFetchSize(1000)