JPA fetchSize不适用于关系(ManyToMany / OneToMany)加载延迟或急切

时间:2014-06-17 17:30:34

标签: java performance hibernate jpa many-to-many

我目前正在尝试优化从数据库加载大量数据的小型应用程序的性能。 我使用标准JPA与Hibernate和Oracle作为数据库。

我有一个ServiceClass,其getAllData方法只执行命名查询loadAllData。 FirstResult和MaxResult也可以设置为限制数据。

Oracle JDBC驱动程序中fetchSize的默认值为10,因此我通过

手动将其设置为100
  

q.setHint(“org.hibernate.fetchSize”,100)

在处理ResultSet时提高性能。

问题是该提示仅适用于由此查询直接加载的实体,但不适用于已解决的渴望或懒惰的关系(ManyToMany / OneToMany)!

服务类:

public class ServiceClass {

    @Inject
    EntityManager entityManager;

    public List<Data> getAllData(Integer limit, Integer offset) {
        Query q = entityManager.createNamedQuery("loadAllData", Data.class);

        if (limit != null && offset != null) {
            q.setFirstResult(offset);
            q.setMaxResults(limit);
        }
        q.setHint("org.hibernate.fetchSize", 100);
        List<Data> result = q.getResultList();
        return result;
    }
}

数据实体:

@Entity
@Table(name="DATA")
@NamedQuery(name = "loadAllData", 
    //hints=@QueryHint(name=QueryHints.FETCH_SIZE, value="100"), 
    query = "SELECT d FROM Data d LEFT JOIN FETCH d.dataA ORDER BY d.dataId")

public class Data {

    @Id
    @Column(name="DATA_ID")
    private String dataId;

    @ManyToOne
    @JoinColumn(name = "A_ID")
    @BatchSize(size = 100)
    private A dataA;

    @OneToMany
    @JoinColumn(name = "DATA_ID")
    @BatchSize(size = 100)
    private Set<B> dataSetB;

    @ManyToMany
    @JoinTable(name = "DATA_C", joinColumns = { @JoinColumn(name = "DATA_ID") }, inverseJoinColumns = { @JoinColumn(name = "C_ID") })
    @BatchSize(size = 100)
    private Set<C> dataSetC;
}

如果加载了Data对象+ A对象,则调试输出显示提示正常工作:

15:55:11.337 [http-bio-8080-exec-3] DEBUG org.hibernate.loader.Loader - Result set row: 0
15:55:11.342 [http-bio-8080-exec-3] DEBUG org.hibernate.loader.Loader - Result row: EntityKey[Data#1], EntityKey[A#5]
15:55:11.348 [http-bio-8080-exec-3] DEBUG org.hibernate.loader.Loader - Result set row: 1
15:55:11.348 [http-bio-8080-exec-3] DEBUG org.hibernate.loader.Loader - Result row: EntityKey[Data#2], EntityKey[A#5]
15:55:11.349 [http-bio-8080-exec-3] DEBUG org.hibernate.loader.Loader - Result set row: 2
15:55:11.349 [http-bio-8080-exec-3] DEBUG org.hibernate.loader.Loader - Result row: EntityKey[Data#3], EntityKey[A#5]
15:55:11.350 [http-bio-8080-exec-3] DEBUG org.hibernate.loader.Loader - Result set row: 3
15:55:11.350 [http-bio-8080-exec-3] DEBUG org.hibernate.loader.Loader - Result row: EntityKey[Data#4], EntityKey[A#5]
15:55:11.351 [http-bio-8080-exec-3] DEBUG org.hibernate.loader.Loader - Result set row: 4
15:55:11.351 [http-bio-8080-exec-3] DEBUG org.hibernate.loader.Loader - Result row: EntityKey[Data#5], EntityKey[A#5]
15:55:11.351 [http-bio-8080-exec-3] DEBUG org.hibernate.loader.Loader - Result set row: 5
15:55:11.351 [http-bio-8080-exec-3] DEBUG org.hibernate.loader.Loader - Result row: EntityKey[Data#6], EntityKey[A#5]
15:55:11.352 [http-bio-8080-exec-3] DEBUG org.hibernate.loader.Loader - Result set row: 6
15:55:11.352 [http-bio-8080-exec-3] DEBUG org.hibernate.loader.Loader - Result row: EntityKey[Data#7], EntityKey[A#5]
15:55:11.353 [http-bio-8080-exec-3] DEBUG org.hibernate.loader.Loader - Result set row: 7
15:55:11.353 [http-bio-8080-exec-3] DEBUG org.hibernate.loader.Loader - Result row: EntityKey[Data#8], EntityKey[A#5]
15:55:11.354 [http-bio-8080-exec-3] DEBUG org.hibernate.loader.Loader - Result set row: 8
15:55:11.354 [http-bio-8080-exec-3] DEBUG org.hibernate.loader.Loader - Result row: EntityKey[Data#9], EntityKey[A#5]
15:55:11.354 [http-bio-8080-exec-3] DEBUG org.hibernate.loader.Loader - Result set row: 9
15:55:11.354 [http-bio-8080-exec-3] DEBUG org.hibernate.loader.Loader - Result row: EntityKey[Data#10], EntityKey[A#5]
15:55:11.355 [http-bio-8080-exec-3] DEBUG org.hibernate.loader.Loader - Result set row: 10
15:55:11.355 [http-bio-8080-exec-3] DEBUG org.hibernate.loader.Loader - Result row: EntityKey[Data#11], EntityKey[A#5]
15:55:11.356 [http-bio-8080-exec-3] DEBUG org.hibernate.loader.Loader - Result set row: 11
15:55:11.356 [http-bio-8080-exec-3] DEBUG org.hibernate.loader.Loader - Result row: EntityKey[Data#12], EntityKey[A#5]
15:55:11.357 [http-bio-8080-exec-3] DEBUG org.hibernate.loader.Loader - Result set row: 12
15:55:11.357 [http-bio-8080-exec-3] DEBUG org.hibernate.loader.Loader - Result row: EntityKey[Data#13], EntityKey[A#5]
15:55:11.357 [http-bio-8080-exec-3] DEBUG org.hibernate.loader.Loader - Result set row: 13
15:55:11.357 [http-bio-8080-exec-3] DEBUG org.hibernate.loader.Loader - Result row: EntityKey[Data#14], EntityKey[A#5]
15:55:11.358 [http-bio-8080-exec-3] DEBUG org.hibernate.loader.Loader - Result set row: 14
15:55:11.358 [http-bio-8080-exec-3] DEBUG org.hibernate.loader.Loader - Result row: EntityKey[Data#15], EntityKey[A#5]
15:55:11.359 [http-bio-8080-exec-3] DEBUG org.hibernate.loader.Loader - Result set row: 15
15:55:11.359 [http-bio-8080-exec-3] DEBUG org.hibernate.loader.Loader - Result row: EntityKey[Data#16], EntityKey[A#5]

如果我没有设置fetchSize提示,处理结果第9行和第10行之间会有一个小差距~100ms(因为默认fetchSize是10)。

OneToMany以及ManyToMany关系稍后会解决,但fetchSize提示不起作用,如您所见:

15:55:11.627 [http-bio-8080-exec-3] DEBUG org.hibernate.loader.Loader - Result set row: 0
15:55:11.627 [http-bio-8080-exec-3] DEBUG org.hibernate.loader.Loader - Result row: EntityKey[B#1109]
15:55:11.627 [http-bio-8080-exec-3] DEBUG org.hibernate.loader.Loader - Result set row: 1
15:55:11.628 [http-bio-8080-exec-3] DEBUG org.hibernate.loader.Loader - Result row: EntityKey[B#1141]
15:55:11.628 [http-bio-8080-exec-3] DEBUG org.hibernate.loader.Loader - Result set row: 2
15:55:11.628 [http-bio-8080-exec-3] DEBUG org.hibernate.loader.Loader - Result row: EntityKey[B#1135]
15:55:11.628 [http-bio-8080-exec-3] DEBUG org.hibernate.loader.Loader - Result set row: 3
15:55:11.629 [http-bio-8080-exec-3] DEBUG org.hibernate.loader.Loader - Result row: EntityKey[B#1172]
15:55:11.629 [http-bio-8080-exec-3] DEBUG org.hibernate.loader.Loader - Result set row: 4
15:55:11.629 [http-bio-8080-exec-3] DEBUG org.hibernate.loader.Loader - Result row: EntityKey[B#1172]
15:55:11.629 [http-bio-8080-exec-3] DEBUG org.hibernate.loader.Loader - Result set row: 5
15:55:11.629 [http-bio-8080-exec-3] DEBUG org.hibernate.loader.Loader - Result row: EntityKey[B#1172]
15:55:11.630 [http-bio-8080-exec-3] DEBUG org.hibernate.loader.Loader - Result set row: 6
15:55:11.630 [http-bio-8080-exec-3] DEBUG org.hibernate.loader.Loader - Result row: EntityKey[B#1192]
15:55:11.630 [http-bio-8080-exec-3] DEBUG org.hibernate.loader.Loader - Result set row: 7
15:55:11.630 [http-bio-8080-exec-3] DEBUG org.hibernate.loader.Loader - Result row: EntityKey[B#1189]
15:55:11.631 [http-bio-8080-exec-3] DEBUG org.hibernate.loader.Loader - Result set row: 8
15:55:11.631 [http-bio-8080-exec-3] DEBUG org.hibernate.loader.Loader - Result row: EntityKey[B#1181]
15:55:11.631 [http-bio-8080-exec-3] DEBUG org.hibernate.loader.Loader - Result set row: 9
15:55:11.631 [http-bio-8080-exec-3] DEBUG org.hibernate.loader.Loader - Result row: EntityKey[B#1181]
15:55:11.730 [http-bio-8080-exec-3] DEBUG org.hibernate.loader.Loader - Result set row: 10
15:55:11.731 [http-bio-8080-exec-3] DEBUG org.hibernate.loader.Loader - Result row: EntityKey[B#1237]
15:55:11.731 [http-bio-8080-exec-3] DEBUG org.hibernate.loader.Loader - Result set row: 11
15:55:11.731 [http-bio-8080-exec-3] DEBUG org.hibernate.loader.Loader - Result row: EntityKey[B#1237]
15:55:11.732 [http-bio-8080-exec-3] DEBUG org.hibernate.loader.Loader - Result set row: 12
15:55:11.732 [http-bio-8080-exec-3] DEBUG org.hibernate.loader.Loader - Result row: EntityKey[B#1237]
15:55:11.733 [http-bio-8080-exec-3] DEBUG org.hibernate.loader.Loader - Result set row: 13
15:55:11.733 [http-bio-8080-exec-3] DEBUG org.hibernate.loader.Loader - Result row: EntityKey[B#1237]
15:55:11.735 [http-bio-8080-exec-3] DEBUG org.hibernate.loader.Loader - Result set row: 14
15:55:11.735 [http-bio-8080-exec-3] DEBUG org.hibernate.loader.Loader - Result row: EntityKey[B#1237]
15:55:11.736 [http-bio-8080-exec-3] DEBUG org.hibernate.loader.Loader - Result set row: 15
15:55:11.736 [http-bio-8080-exec-3] DEBUG org.hibernate.loader.Loader - Result row: EntityKey[B#1235]
15:55:11.736 [http-bio-8080-exec-3] DEBUG org.hibernate.loader.Loader - Result set row: 16

您可以看到,由于数据库的网络延迟,结果行9和10之间需要约100毫秒。因此使用的默认fetchSize为10,而不是我在查询中设置的提示。

我还尝试直接在命名查询中设置提示(注释行)或将fetchType设置为EAGER,但效果相同。

这是一个错误还是设计?有谁知道如何解决这个问题?

修改

我到目前为止唯一的解决方案是将fetchSize设置为persistence.xml中的属性,但我不想将其指定为全局设置。

  

<property name="hibernate.jdbc.fetch_size" value="100"/>

0 个答案:

没有答案