为什么我的JPA查询在每次循环迭代时变慢?

时间:2015-03-16 10:15:31

标签: java jpa h2

我需要从db表中加载所有数据,然后将其放入搜索索引(elasticsearch具体)。 (在我的案例中,使用ES河不是一种选择)

我的经历如下: 我有一个特定批次sice的查询(例如5000个条目)。我在循环中执行该查询以获取批次,每次迭代都会增加偏移量。第一次迭代需要19秒。第四次迭代已经有50秒了。

在我的情况下,该列有700万行,但生产数据至少会增加3倍,所以如果执行时间不断增长,我的方法就无法实现(已经有700万个条目) )。 稍后我可以使用多个线程来确定选择数据,但首先我想保持每个选择的时间不变(如果可能)。

我想知道性能损失来自哪里,以及如何避免或至少减少它?

我选择的表只有一个id(长)和一个文档(clob)列。

我正在使用一个拥有700万行的h2,也许这就是原因?我不熟悉这种表格大小的h2性能。

我的第一个猜测是垃圾收集器,所以我看了VisualVM ......看起来还不错。 已经尝试在每次迭代时在会话工厂中清除所有缓存,但行为没有变化,所以我想我在这里错误的轨道。

EntityManager em = persistenceUtils.openEm();
//        em.setProperty("javax.persistence.cache.storeMode",      CacheStoreMode.BYPASS);
//        em.setProperty("javax.persistence.cache.retrieveMode",      CacheRetrieveMode.BYPASS);
    Query selectAll = em.createQuery("Select d from Document d order by d.id");

    List<Document> documents = selectAll.setFirstResult(0).setMaxResults(BATCH_SIZE).getResultList();
    List<ListenableActionFuture<BulkResponse>> bulkResponses = Lists.newArrayList(addBulkIndexRequests(documents, client));
    int i = 1;
    while(documents != null && !documents.isEmpty()) {
        long batchStartTime = System.nanoTime();
        documents = selectAll.setFirstResult(i*BATCH_SIZE).setMaxResults(BATCH_SIZE).getResultList();
        long batchEndTime = System.nanoTime();
        System.out.println("+++ SELECTED BATCH " + i + "in" + (batchEndTime - batchStartTime) / 1000000000.0 +  "SECONDS +++");
        addBulkIndexRequests(documents, client);
        System.out.println("+++ ADDED BATCH " + i + " +++");
        i++;
    }
    persistenceUtils.closeEm(em);

1 个答案:

答案 0 :(得分:-1)

似乎H2是这里的问题。在本地安装了一个oracle 11g并对其运行了select查询。每批1000个条目的访问时间一直在0.44左右。

但必须要说的是,我还在我针对oracle DB测试的解决方案中实施了Predrag marcic和Andrei的建议。