【问题标题】:Hibernate search mass index with Spring Data JPA使用 Spring Data JPA 进行休眠搜索质量索引
【发布时间】:2013-05-29 15:43:20
【问题描述】:

我有一个刚刚转换为 Spring Data JPA 的项目。该项目使用 Hibernate Search,我需要一种方法来索引数据库中现有的(约 1500 万条)记录。

由于我要处理如此大量的记录,我不能使用 Hibernate Search 的 MassIndexer,因为这会导致内存不足的问题。

根据我读到的内容(这里:http://docs.jboss.org/hibernate/search/4.2/reference/en-US/html/manual-index-changes.html#search-batchindex),建议的方法是这样的:

fullTextSession.setFlushMode(FlushMode.MANUAL);
fullTextSession.setCacheMode(CacheMode.IGNORE);
transaction = fullTextSession.beginTransaction();
//Scrollable results will avoid loading too many objects in memory
ScrollableResults results = fullTextSession.createCriteria( Email.class )
    .setFetchSize(BATCH_SIZE)
    .scroll( ScrollMode.FORWARD_ONLY );
int index = 0;
while( results.next() ) {
    index++;
    fullTextSession.index( results.get(0) ); //index each element
    if (index % BATCH_SIZE == 0) {
        fullTextSession.flushToIndexes(); //apply changes to indexes
        fullTextSession.clear(); //free memory since the queue is processed
    }
}
transaction.commit();

但是,我想注入我在 Spring 中配置的实体管理器。

我读到我可以通过在实体管理器上使用getDelegate() 方法来获取 Hibernate 会话,但这会导致一个错误,指出一旦我尝试在会话:

public void reindexListings() throws InterruptedException {

   Session session = (Session) em.getDelegate();

   FullTextSession fts = Search.getFullTextSession(session);

   try {
      fts.setFlushMode(FlushMode.MANUAL);
   } catch (Exception e) {
      // Throws stack trace here stating that the Hibernate session is closed.
      e.printStackTrace();
   }

   fts.setCacheMode(CacheMode.IGNORE);
   Transaction transaction = fts.beginTransaction();

   // Scrollable results will avoid loading too many objects in memory
   ScrollableResults results = fts.createCriteria(EListing.class)
         .setFetchSize(25).scroll(ScrollMode.FORWARD_ONLY);
   int index = 0;
   while (results.next()) {
      index++;
      fts.index(results.get(0)); // index each element
      if ((index % 25) == 0) {
         fts.flushToIndexes(); // apply changes to indexes
         fts.clear(); // free memory since the queue is processed
      }
   }

   transaction.commit();

}

我还读到我可以使用HibernateUtil 来获取会话(http://www.17od.com/2006/11/06/using-managed-sessions-in-hibernate-to-ease-unit-testing/),但同样,这并没有使用我的实体管理器。

不确定到目前为止我是否走在正确的轨道上,或者我是否需要以完全不同的方式来做这件事,但到目前为止我发现的任何东西似乎都不起作用。

【问题讨论】:

    标签: hibernate spring-data-jpa hibernate-search


    【解决方案1】:

    MassIndexer 专为大量数据而设计,不会导致内存不足问题。

    如果您使用的是 MySQL,您是否注意到参考上的警告:

    MassIndexer 使用仅向前滚动的结果来迭代 要加载的主键,但 MySQL 的 JDBC 驱动程序将加载所有 内存中的值;为避免这种“优化”,请将 idFetchSize 设置为 整数.MIN_VALUE。

    如果这不是问题,请尝试将 MassIndexer 选项设置为不太激进的值:

    fullTextSession.createIndexer()
       .threadsForSubsequentFetching( X )
       .threadsToLoadObjects( Y )
       .batchSizeToLoadObjects( Z )
       .progressMonitor( progressMonitor )
       .startAndWait();
    

    或者只是将你的堆大小调整为更大的值:重新索引所有这些东西需要时间,所以如果你能给它更多的内存,它会显着提高效率。

    使用 MassIndexer.limitIndexedObjectsTo(long) 来试验不同的值,但请记住,至少需要 15 分钟才能达到平均性能。

    【讨论】:

    • 感谢您的回复。原来我的问题毕竟不是 MassIndexer。我的实体关系生成的查询导致没有候选索引。我的假设是,MassIndexer 将文档保存在内存中,直到过程结束,因为我有太多实体要循环,所以这个过程从未完成。设置索引对象的限制使我能够完成索引过程并告诉我情况并非如此。从那里,我能够进一步调查并发现真正的问题。再次感谢。
    猜你喜欢
    • 1970-01-01
    • 2021-07-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-19
    • 1970-01-01
    • 2014-08-31
    相关资源
    最近更新 更多