Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/330.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 避免N+;嵌套对象中的1个问题?_Java_Hibernate_Query Optimization - Fatal编程技术网

Java 避免N+;嵌套对象中的1个问题?

Java 避免N+;嵌套对象中的1个问题?,java,hibernate,query-optimization,Java,Hibernate,Query Optimization,我遇到了低效的Hibernate查询,我认为原因是我在别处读到的所谓的N+1问题。然而,我不知道如何解决这个问题,因为我的对象是嵌套的,而且我在网上看到的大多数示例解决方案都很琐碎 这是我申请的简要说明 我有一个ExecutionTrace类,它与TraceLine类有一对多的关系TraceLine又与TraceReference类有一对多的关系。每个类都有一个id属性,由Hibernate生成。(所有类都包含一些成员变量,但现在我将省略它们。) 在我的应用程序中,我正在查询一个特定的Execu

我遇到了低效的Hibernate查询,我认为原因是我在别处读到的所谓的N+1问题。然而,我不知道如何解决这个问题,因为我的对象是嵌套的,而且我在网上看到的大多数示例解决方案都很琐碎

这是我申请的简要说明

我有一个
ExecutionTrace
类,它与
TraceLine
类有一对多的关系
TraceLine
又与
TraceReference
类有一对多的关系。每个类都有一个id属性,由Hibernate生成。(所有类都包含一些成员变量,但现在我将省略它们。)

在我的应用程序中,我正在查询一个特定的
ExecutionTrace
,然后我的应用程序将遍历它的所有
TraceLine
对象及其
TraceReference
对象。因此,我将所有这些关系的
LazyCollectionOption
设置为
false

// ExecutionTrace.java:
...
@Id @GeneratedValue
@Column(name = "file_id")
public long id;
...
@OneToMany(mappedBy = "container_trace_", cascade = CascadeType.ALL)
@LazyCollection(LazyCollectionOption.FALSE)
@OrderBy(clause = "id")
public List<TraceLine> lines_ = new ArrayList<TraceLine>();
...


// TraceLine.java:
...
@Id @GeneratedValue
@Column(name = "trace_line_id")
@Index(name = "traceIDIndex")
public long id;
...
@ManyToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "file_id")
@LazyCollection(LazyCollectionOption.TRUE)
public ExecutionTrace container_trace_;
...
@OneToMany(mappedBy = "trace_line_", cascade = CascadeType.ALL)
@LazyCollection(LazyCollectionOption.FALSE)
@OrderBy(clause = "id")
public List<TraceReference> trace_references_ = new ArrayList<TraceReference>();
...


// TraceReference.java:
...
@Id @GeneratedValue
@Column(name = "trace_reference_id")
@Index(name="TraceReferenceIDIndex")
public long id;
...
@ManyToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "trace_line_id")
@LazyCollection(LazyCollectionOption.TRUE)
public TraceLine trace_line_;
...
在我的一个简单测试用例中,有1个
ExecutionTrace
对象,其中包含645个
TraceLine
对象,每个对象包含1到5个
TraceReference
对象。在普通硬件上,查询和迭代所有查询的代码需要50秒以上的时间。数据库PostgreSQL与应用程序运行在同一台计算机上

查看Hibernate抛出的SQL查询,我注意到:

  • 有一个查询选择所有
    轨迹线
    对象。这很好
  • 有645个查询要选择
    TraceReference
    对象。这很糟糕。此外,它们都有大量的外部联接,这使得它们效率低下
例如,这里有一个对TraceReference的查询:

    select
        trace_refe0_.trace_line_id as trace5_6_18_,
        trace_refe0_.trace_reference_id as trace1_18_,
        trace_refe0_.trace_reference_id as trace1_7_17_,
        trace_refe0_.new_value as new2_7_17_,
        trace_refe0_.old_value as old3_7_17_,
        trace_refe0_.operand_id as operand4_7_17_,
        trace_refe0_.trace_line_id as trace5_7_17_,
        operand1_.operand_id as operand1_11_0_,
        operand1_.operand_index as operand2_11_0_,
        operand1_.is_dest as is3_11_0_,
        operand1_.is_source as is4_11_0_,
        operand1_.operand_size as operand5_11_0_,
        operand1_.operand_u_prop_id as operand6_11_0_,
        operand1_.maps_to_variable as maps7_11_0_,
        operandtyp2_.operand_prop_id as operand2_12_1_,
        operandtyp2_1_.constant_value as constant1_13_1_,
        operandtyp2_2_.register_name as register1_14_1_,
        operandtyp2_4_.base_operand_id as base2_16_1_,
        operandtyp2_4_.displacement_operand_id as displace3_16_1_,
        operandtyp2_4_.index_operand_id as index4_16_1_,
        operandtyp2_4_.ml_name as ml1_16_1_,
        operandtyp2_4_.scale_operand_id as scale5_16_1_,
        operandtyp2_.DTYPE as DTYPE12_1_,
        register3_.operand_prop_id as operand2_12_2_,
        register3_1_.register_name as register1_14_2_,
        constant4_.operand_prop_id as operand2_12_3_,
        constant4_1_.constant_value as constant1_13_3_,
        register5_.operand_prop_id as operand2_12_4_,
        register5_1_.register_name as register1_14_4_,
        constant6_.operand_prop_id as operand2_12_5_,
        constant6_1_.constant_value as constant1_13_5_,
        variable7_.variable_id as variable1_18_6_,
        variable7_.file_id as file6_18_6_,
        variable7_.function_id as function7_18_6_,
        variable7_.variable_is_argument as variable2_18_6_,
        variable7_.variable_is_global as variable3_18_6_,
        variable7_.variable_is_static as variable4_18_6_,
        variable7_.variable_name as variable5_18_6_,
        variable7_.data_type_id as data8_18_6_,
        sourcefile8_.file_id as file2_0_7_,
        sourcefile8_.file_path as file3_0_7_,
        sourcefile8_.file_name as file4_0_7_,
        sourcefile8_.source_lang as source5_0_7_,
        function9_.function_id as function1_8_8_,
        function9_.file_id as file6_8_8_,
        function9_.function_end_address as function2_8_8_,
        function9_.function_address as function3_8_8_,
        function9_.function_name as function4_8_8_,
        function9_.function_is_static as function5_8_8_,
        sourcefile10_.file_id as file2_0_9_,
        sourcefile10_.file_path as file3_0_9_,
        sourcefile10_.file_name as file4_0_9_,
        sourcefile10_.source_lang as source5_0_9_,
        datatype11_.data_type_id as data2_19_10_,
        datatype11_.defined_by as defined5_19_10_,
        datatype11_.data_type_length as data3_19_10_,
        datatype11_.data_type_name as data4_19_10_,
        datatype11_2_.pointer_to as pointer1_20_10_,
        datatype11_3_.array_size as array1_21_10_,
        datatype11_3_.contains_type as contains2_21_10_,
        datatype11_4_.enumerator_count as enumerator1_22_10_,
        datatype11_5_.type_ as type1_24_10_,
        datatype11_6_.constant_of_type as constant1_25_10_,
        datatype11_7_.return_type as return1_27_10_,
        datatype11_.DTYPE as DTYPE19_10_,
        sourcefile12_.file_id as file2_0_11_,
        sourcefile12_.file_path as file3_0_11_,
        sourcefile12_.file_name as file4_0_11_,
        sourcefile12_.source_lang as source5_0_11_,
        datatype13_.data_type_id as data2_19_12_,
        datatype13_.defined_by as defined5_19_12_,
        datatype13_.data_type_length as data3_19_12_,
        datatype13_.data_type_name as data4_19_12_,
        datatype13_2_.pointer_to as pointer1_20_12_,
        datatype13_3_.array_size as array1_21_12_,
        datatype13_3_.contains_type as contains2_21_12_,
        datatype13_4_.enumerator_count as enumerator1_22_12_,
        datatype13_5_.type_ as type1_24_12_,
        datatype13_6_.constant_of_type as constant1_25_12_,
        datatype13_7_.return_type as return1_27_12_,
        datatype13_.DTYPE as DTYPE19_12_,
        datatype14_.data_type_id as data2_19_13_,
        datatype14_.defined_by as defined5_19_13_,
        datatype14_.data_type_length as data3_19_13_,
        datatype14_.data_type_name as data4_19_13_,
        datatype14_2_.pointer_to as pointer1_20_13_,
        datatype14_3_.array_size as array1_21_13_,
        datatype14_3_.contains_type as contains2_21_13_,
        datatype14_4_.enumerator_count as enumerator1_22_13_,
        datatype14_5_.type_ as type1_24_13_,
        datatype14_6_.constant_of_type as constant1_25_13_,
        datatype14_7_.return_type as return1_27_13_,
        datatype14_.DTYPE as DTYPE19_13_,
        datatype15_.data_type_id as data2_19_14_,
        datatype15_.defined_by as defined5_19_14_,
        datatype15_.data_type_length as data3_19_14_,
        datatype15_.data_type_name as data4_19_14_,
        datatype15_2_.pointer_to as pointer1_20_14_,
        datatype15_3_.array_size as array1_21_14_,
        datatype15_3_.contains_type as contains2_21_14_,
        datatype15_4_.enumerator_count as enumerator1_22_14_,
        datatype15_5_.type_ as type1_24_14_,
        datatype15_6_.constant_of_type as constant1_25_14_,
        datatype15_7_.return_type as return1_27_14_,
        datatype15_.DTYPE as DTYPE19_14_,
        datatype16_.data_type_id as data2_19_15_,
        datatype16_.defined_by as defined5_19_15_,
        datatype16_.data_type_length as data3_19_15_,
        datatype16_.data_type_name as data4_19_15_,
        datatype16_2_.pointer_to as pointer1_20_15_,
        datatype16_3_.array_size as array1_21_15_,
        datatype16_3_.contains_type as contains2_21_15_,
        datatype16_4_.enumerator_count as enumerator1_22_15_,
        datatype16_5_.type_ as type1_24_15_,
        datatype16_6_.constant_of_type as constant1_25_15_,
        datatype16_7_.return_type as return1_27_15_,
        datatype16_.DTYPE as DTYPE19_15_,
        datatype17_.data_type_id as data2_19_16_,
        datatype17_.defined_by as defined5_19_16_,
        datatype17_.data_type_length as data3_19_16_,
        datatype17_.data_type_name as data4_19_16_,
        datatype17_2_.pointer_to as pointer1_20_16_,
        datatype17_3_.array_size as array1_21_16_,
        datatype17_3_.contains_type as contains2_21_16_,
        datatype17_4_.enumerator_count as enumerator1_22_16_,
        datatype17_5_.type_ as type1_24_16_,
        datatype17_6_.constant_of_type as constant1_25_16_,
        datatype17_7_.return_type as return1_27_16_,
        datatype17_.DTYPE as DTYPE19_16_ 
    from
        TraceReference trace_refe0_ 
    left outer join
        Operand operand1_ 
            on trace_refe0_.operand_id=operand1_.operand_id 
    left outer join
        OperandProperties operandtyp2_ 
            on operand1_.operand_u_prop_id=operandtyp2_.operand_prop_id 
    left outer join
        Constant operandtyp2_1_ 
            on operandtyp2_.operand_prop_id=operandtyp2_1_.operand_prop_id 
    left outer join
        Register operandtyp2_2_ 
            on operandtyp2_.operand_prop_id=operandtyp2_2_.operand_prop_id 
    left outer join
        UnknownOperandProperties operandtyp2_3_ 
            on operandtyp2_.operand_prop_id=operandtyp2_3_.operand_prop_id 
    left outer join
        MemoryLocation operandtyp2_4_ 
            on operandtyp2_.operand_prop_id=operandtyp2_4_.operand_prop_id 
    left outer join
        OperandProperties register3_ 
            on operandtyp2_4_.base_operand_id=register3_.operand_prop_id 
    left outer join
        Register register3_1_ 
            on register3_.operand_prop_id=register3_1_.operand_prop_id 
    left outer join
        OperandProperties constant4_ 
            on operandtyp2_4_.displacement_operand_id=constant4_.operand_prop_id 
    left outer join
        Constant constant4_1_ 
            on constant4_.operand_prop_id=constant4_1_.operand_prop_id 
    left outer join
        OperandProperties register5_ 
            on operandtyp2_4_.index_operand_id=register5_.operand_prop_id 
    left outer join
        Register register5_1_ 
            on register5_.operand_prop_id=register5_1_.operand_prop_id 
    left outer join
        OperandProperties constant6_ 
            on operandtyp2_4_.scale_operand_id=constant6_.operand_prop_id 
    left outer join
        Constant constant6_1_ 
            on constant6_.operand_prop_id=constant6_1_.operand_prop_id 
    left outer join
        Variable variable7_ 
            on operand1_.maps_to_variable=variable7_.variable_id 
    left outer join
        FileOnDisk sourcefile8_ 
            on variable7_.file_id=sourcefile8_.file_id 
    left outer join
        ObjectFile sourcefile8_1_ 
            on sourcefile8_.file_id=sourcefile8_1_.file_id 
    left outer join
        SourceFile sourcefile8_2_ 
            on sourcefile8_.file_id=sourcefile8_2_.file_id 
    left outer join
        SourceFunction function9_ 
            on variable7_.function_id=function9_.function_id 
    left outer join
        FileOnDisk sourcefile10_ 
            on function9_.file_id=sourcefile10_.file_id 
    left outer join
        ObjectFile sourcefile10_1_ 
            on sourcefile10_.file_id=sourcefile10_1_.file_id 
    left outer join
        SourceFile sourcefile10_2_ 
            on sourcefile10_.file_id=sourcefile10_2_.file_id 
    left outer join
        DataType datatype11_ 
            on variable7_.data_type_id=datatype11_.data_type_id 
    left outer join
        Pointer datatype11_1_ 
            on datatype11_.data_type_id=datatype11_1_.data_type_id 
    left outer join
        Pointer datatype11_2_ 
            on datatype11_.data_type_id=datatype11_2_.data_type_id 
    left outer join
        SourceArray datatype11_3_ 
            on datatype11_.data_type_id=datatype11_3_.data_type_id 
    left outer join
        Enum datatype11_4_ 
            on datatype11_.data_type_id=datatype11_4_.data_type_id 
    left outer join
        Typedef datatype11_5_ 
            on datatype11_.data_type_id=datatype11_5_.data_type_id 
    left outer join
        ConstantType datatype11_6_ 
            on datatype11_.data_type_id=datatype11_6_.data_type_id 
    left outer join
        FunctionType datatype11_7_ 
            on datatype11_.data_type_id=datatype11_7_.data_type_id 
    left outer join
        FileOnDisk sourcefile12_ 
            on datatype11_.defined_by=sourcefile12_.file_id 
    left outer join
        ObjectFile sourcefile12_1_ 
            on sourcefile12_.file_id=sourcefile12_1_.file_id 
    left outer join
        SourceFile sourcefile12_2_ 
            on sourcefile12_.file_id=sourcefile12_2_.file_id 
    left outer join
        DataType datatype13_ 
            on datatype11_2_.pointer_to=datatype13_.data_type_id 
    left outer join
        Pointer datatype13_1_ 
            on datatype13_.data_type_id=datatype13_1_.data_type_id 
    left outer join
        Pointer datatype13_2_ 
            on datatype13_.data_type_id=datatype13_2_.data_type_id 
    left outer join
        SourceArray datatype13_3_ 
            on datatype13_.data_type_id=datatype13_3_.data_type_id 
    left outer join
        Enum datatype13_4_ 
            on datatype13_.data_type_id=datatype13_4_.data_type_id 
    left outer join
        Typedef datatype13_5_ 
            on datatype13_.data_type_id=datatype13_5_.data_type_id 
    left outer join
        ConstantType datatype13_6_ 
            on datatype13_.data_type_id=datatype13_6_.data_type_id 
    left outer join
        FunctionType datatype13_7_ 
            on datatype13_.data_type_id=datatype13_7_.data_type_id 
    left outer join
        DataType datatype14_ 
            on datatype13_3_.contains_type=datatype14_.data_type_id 
    left outer join
        Pointer datatype14_1_ 
            on datatype14_.data_type_id=datatype14_1_.data_type_id 
    left outer join
        Pointer datatype14_2_ 
            on datatype14_.data_type_id=datatype14_2_.data_type_id 
    left outer join
        SourceArray datatype14_3_ 
            on datatype14_.data_type_id=datatype14_3_.data_type_id 
    left outer join
        Enum datatype14_4_ 
            on datatype14_.data_type_id=datatype14_4_.data_type_id 
    left outer join
        Typedef datatype14_5_ 
            on datatype14_.data_type_id=datatype14_5_.data_type_id 
    left outer join
        ConstantType datatype14_6_ 
            on datatype14_.data_type_id=datatype14_6_.data_type_id 
    left outer join
        FunctionType datatype14_7_ 
            on datatype14_.data_type_id=datatype14_7_.data_type_id 
    left outer join
        DataType datatype15_ 
            on datatype14_5_.type_=datatype15_.data_type_id 
    left outer join
        Pointer datatype15_1_ 
            on datatype15_.data_type_id=datatype15_1_.data_type_id 
    left outer join
        Pointer datatype15_2_ 
            on datatype15_.data_type_id=datatype15_2_.data_type_id 
    left outer join
        SourceArray datatype15_3_ 
            on datatype15_.data_type_id=datatype15_3_.data_type_id 
    left outer join
        Enum datatype15_4_ 
            on datatype15_.data_type_id=datatype15_4_.data_type_id 
    left outer join
        Typedef datatype15_5_ 
            on datatype15_.data_type_id=datatype15_5_.data_type_id 
    left outer join
        ConstantType datatype15_6_ 
            on datatype15_.data_type_id=datatype15_6_.data_type_id 
    left outer join
        FunctionType datatype15_7_ 
            on datatype15_.data_type_id=datatype15_7_.data_type_id 
    left outer join
        DataType datatype16_ 
            on datatype15_6_.constant_of_type=datatype16_.data_type_id 
    left outer join
        Pointer datatype16_1_ 
            on datatype16_.data_type_id=datatype16_1_.data_type_id 
    left outer join
        Pointer datatype16_2_ 
            on datatype16_.data_type_id=datatype16_2_.data_type_id 
    left outer join
        SourceArray datatype16_3_ 
            on datatype16_.data_type_id=datatype16_3_.data_type_id 
    left outer join
        Enum datatype16_4_ 
            on datatype16_.data_type_id=datatype16_4_.data_type_id 
    left outer join
        Typedef datatype16_5_ 
            on datatype16_.data_type_id=datatype16_5_.data_type_id 
    left outer join
        ConstantType datatype16_6_ 
            on datatype16_.data_type_id=datatype16_6_.data_type_id 
    left outer join
        FunctionType datatype16_7_ 
            on datatype16_.data_type_id=datatype16_7_.data_type_id 
    left outer join
        DataType datatype17_ 
            on datatype16_7_.return_type=datatype17_.data_type_id 
    left outer join
        Pointer datatype17_1_ 
            on datatype17_.data_type_id=datatype17_1_.data_type_id 
    left outer join
        Pointer datatype17_2_ 
            on datatype17_.data_type_id=datatype17_2_.data_type_id 
    left outer join
        SourceArray datatype17_3_ 
            on datatype17_.data_type_id=datatype17_3_.data_type_id 
    left outer join
        Enum datatype17_4_ 
            on datatype17_.data_type_id=datatype17_4_.data_type_id 
    left outer join
        Typedef datatype17_5_ 
            on datatype17_.data_type_id=datatype17_5_.data_type_id 
    left outer join
        ConstantType datatype17_6_ 
            on datatype17_.data_type_id=datatype17_6_.data_type_id 
    left outer join
        FunctionType datatype17_7_ 
            on datatype17_.data_type_id=datatype17_7_.data_type_id 
    where
        trace_refe0_.trace_line_id=? 
    order by
        trace_refe0_.trace_reference_id
TRACE [main] 06/26/13 10:00:54 preparing statement
TRACE [main] 06/26/13 10:00:54 binding parameter [1] as [BIGINT] - 82883
我尝试修改查询,以便它执行一些内部联接:

    String queryString =    " from ExecutionTrace as et " +
               "inner join fetch et.lines_ as lines " +
        "where et.hash_ = '"+ f_hash +"'";
    String queryString = 
    " from ExecutionTrace as et " +
       "inner join fetch et.lines_ as lines " +
       "inner join fetch lines.trace_references_ " +
    "where et.hash_ = '"+ f_hash +"'";
这导致0个查询选择
TraceLine
s,645个查询选择
TraceReference
s。没有帮助。然后我尝试了多个内部联接:

    String queryString =    " from ExecutionTrace as et " +
               "inner join fetch et.lines_ as lines " +
        "where et.hash_ = '"+ f_hash +"'";
    String queryString = 
    " from ExecutionTrace as et " +
       "inner join fetch et.lines_ as lines " +
       "inner join fetch lines.trace_references_ " +
    "where et.hash_ = '"+ f_hash +"'";
这导致了一个例外:

Exception in thread "main" org.hibernate.loader.MultipleBagFetchException: cannot simultaneously fetch multiple bags.

我觉得我即将解决这个问题,但只是错过了一些简单的东西。

在做了一些研究和实验后,我找到了两种解决这个问题的可能方法,每种方法都有各自的优缺点

1。使用子选择提取模式

使用
@Fetch
注释使Hibernate生成子选择查询:

@OneToMany(mappedBy = "container_trace_", cascade = CascadeType.ALL)
@LazyCollection(LazyCollectionOption.TRUE)
@OrderBy(clause = "id")
@Fetch(FetchMode.SUBSELECT)
public List<TraceLine> lines_ = new ArrayList<TraceLine>();
  • 赞成:这有效地将选择的数量减少了10倍
  • 赞成:不会耗尽内存
  • 缺点:如果
    TraceLine
    对象的数量很大,仍然会有大量的选择

这两种解决方案都不是完美的。在我的应用程序中,我使用了批处理

这个
MultipleBagFetchException
是IIRC引起的,因为您的集合都是列表。在这种情况下,Hibernate不知道如何执行查询,因为列表是排序的。如果可能,或者如果您有专门的可能性对
TraceLine
s/
TraceReference
s进行排序,那么您可以使用
集合