Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/hibernate/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java HIbernate条件查询深度联接的性能问题_Java_Hibernate_Join - Fatal编程技术网

Java HIbernate条件查询深度联接的性能问题

Java HIbernate条件查询深度联接的性能问题,java,hibernate,join,Java,Hibernate,Join,我面临涉及深度联接的hibernate条件查询的性能问题。 当我在数据库中直接执行hibernate生成的查询时,结果会在几秒钟内返回。 通过hibernate,它需要一些与结果大小成指数关系的时间。如果有10个结果,则需要1秒。如果有大约500个结果,那么它会持续15秒,如果超过1000个,那么它会持续30秒,就像这样 下面是hibernate生成的查询和我正在使用的Java代码。在下面的日志中,您可以看到打印查询后,30秒后返回结果。 我在hibernate中使用元组查询,并使用结果转换器将

我面临涉及深度联接的hibernate条件查询的性能问题。 当我在数据库中直接执行hibernate生成的查询时,结果会在几秒钟内返回。 通过hibernate,它需要一些与结果大小成指数关系的时间。如果有10个结果,则需要1秒。如果有大约500个结果,那么它会持续15秒,如果超过1000个,那么它会持续30秒,就像这样

下面是hibernate生成的查询和我正在使用的Java代码。在下面的日志中,您可以看到打印查询后,30秒后返回结果。 我在hibernate中使用元组查询,并使用结果转换器将结果映射到DTO。 Hibernate版本是5.3.7

我已经启用了hibernate调试来获取一些详细信息,并且hibernate在结果集中循环的时间如下所述。 6465条记录被获取,我认为hibernate需要将近30秒的时间循环遍历每个结果集。 这正常吗

我已将下面的实际表名替换为虚拟表名,因为这是客户机代码的一部分

生成的查询

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)