Hibernate Search(基于version3.4)--第六章Manual index changes

Manual index changes

 

当Hibernate core应用实体类的改变到数据库,Hibernate Search也会自动地探测这些改变并更新index(除非禁用事件监听器)。有时候并不是通过Hibernate来修改数据库的数据,像当还原数据库的 备份或数据是不同的方式生成的。对于这样的用例,Hibernate Search暴露了Manual Index API来明确地更新,删除index中的单一实体,或重建整个数据库的index,或删除某个指定类型的所有引用。

 

所有的这些方法只影响 Lucene Index,并不会修改数据库。

 

6.1. Adding instances to the index

使用FullTextSession.index(T entity),你可以直接地添加或更新一个具体的对象实例到index。如果该实例已经存在index中,那么就会更新index。index的改变只能在transaction commit时应用。

 

Example 6.1. Indexing an entity via FullTextSession.index(T entity)

 

Java代码   收藏代码
  1. FullTextSession fullTextSession = Search.getFullTextSession(session);  
  2. Transaction tx = fullTextSession.beginTransaction();  
  3. Object customer = fullTextSession.load( Customer.class8 );  
  4. fullTextSession.index(customer);  
  5. tx.commit(); //index only updated at commit time  

  

6.2. Deleting instances from the index

也可以不删除数据库数据的情况下,删除指定类的Lucene index。这个操作称为purging,也是通过FullTextSession来完成的。

 

Example 6.2. Purging a specific instance of an entity from the index

 

Java代码   收藏代码
  1. FullTextSession fullTextSession = Search.getFullTextSession(session);  
  2. Transaction tx = fullTextSession.beginTransaction();  
  3. for (Customer customer : customers) {  
  4.     fullTextSession.purge( Customer.class, customer.getId() );  
  5. }  
  6. tx.commit(); //index is updated at commit time  

 

 

 

purging只会移除index中指定id的实体,对数据库不产生影响。

 

如果你需要移除某个类的所有index,你可以使用purgeAll方法。这个操作也会移除类的子类。

Example 6.3. Purging all instances of an entity from the index

 

Java代码   收藏代码
  1. FullTextSession fullTextSession = Search.getFullTextSession(session);  
  2. Transaction tx = fullTextSession.beginTransaction();  
  3. fullTextSession.purgeAll( Customer.class );  
  4. //optionally optimize the index  
  5. //fullTextSession.getSearchFactory().optimize( Customer.class );  
  6. tx.commit(); //index changes are applied at commit time   

 

 

推荐在purging操作之后optimize the index。

 

Note:方法index,purge,purgeAll同样适用FullTextEntityManager。

 

Note:所有manual indexing methods (index, purge and purgeAll)只会影响index,不会影响数据库,然而它们必须是事务的,在事务提交之前或使用flushToIndexes方法之前,它们是不会被应用的

 

 

6.3. Rebuilding the whole index

 

如果你改变了实体到index的映射,这样就需要更新整个index。例如你要改变一个已存在的field的analyzer,你需要重建 index。同样地,如果数据库被重置了(还原备份),你也需要重建index。Hibernate Search提供了两个主要策略来达到重建index的目的:

 

  • 使用FullTextSession.index()一个个地更新实体,然后对应地使用FullTextSession.flushToIndexes()方法来刷新缓存。
  • Use a MassIndexer.

 

 

6.3.1. Using flushToIndexes()

 

该策略对应使用了FullTextSession.purgeAll()或FullTextSession.index(),然而这些方法会存在内 存和性能约束。为了最大性能体现,Hibernate Search捆绑了所有index操作直到commit time来执行这些操作。如果你希望添加大量的index数据,那么你需要小心内存消耗,因为所有的document保存在一个队列中直到事务提交。如果 你不同期性地清空队列,你可能潜在面对一个OutOfMemoryException:清空队列可以使用 fullTextSession.flushToIndexes()方法。每一次调用fullTextSession.flushToIndexes() (或事务提交),捆绑队列会应用于index。注意,当flush,所应用的改变不能roll back。

 

Example 6.4. Index rebuilding using index() and flushToIndexes()

 

Java代码   收藏代码
  1. fullTextSession.setFlushMode(FlushMode.MANUAL);  
  2. fullTextSession.setCacheMode(CacheMode.IGNORE);  
  3. transaction = fullTextSession.beginTransaction();  
  4. //Scrollable results will avoid loading too many objects in memory  
  5. ScrollableResults results = fullTextSession.createCriteria( Email.class )  
  6.     .setFetchSize(BATCH_SIZE)  
  7.     .scroll( ScrollMode.FORWARD_ONLY );  
  8. int index = 0;  
  9. while( results.next() ) {  
  10.     index++;  
  11.     fullTextSession.index( results.get(0) ); //index each element  
  12.     if (index % BATCH_SIZE == 0) {  
  13.         fullTextSession.flushToIndexes(); //apply changes to indexes  
  14.         fullTextSession.clear(); //free memory since the queue is processed  
  15.     }  
  16. }  
  17. transaction.commit();  

 

 

Note:hibernate.search.worker.batch_size已经被弃用,明确的API声明能提供更好的控制。

 

使用一个batch size可以保证你的应用不会out of memory:一个大的batch size,从数据库抓取数据的速度更快,不过需要更多的内存。

 

 

6.3.2. Using a MassIndexer

Hibernate Search的MassIndexer使用多个平行线程来重建index;你可以指定哪些实体需要重载或重建index。这个方法有着最优性能,但要求设置应用为maintenance模式:当MassIndexer繁忙时,不推荐查询index。

 

Example 6.5. Index rebuilding using a MassIndexer

 

Java代码   收藏代码
  1. fullTextSession.createIndexer().startAndWait();  

 

这句代码会重建index,先删除它并重新从数据库中加载所有实体。虽然使用很简单,但推荐做些调整去提高速度:有些参数需要配置。

 

Warning:在MassIndexer处理过程中,index的内容是未定义的,因此在重建过程中应该确保没有人查询index。如果有人在查询index,并不会破坏该index,只是有些结果会丢失。

 

Example 6.6. Using a tuned MassIndexer

 

Java代码   收藏代码
  1. fullTextSession  
  2.  .createIndexer( User.class )  
  3.  .batchSizeToLoadObjects( 25 )  
  4.  .cacheMode( CacheMode.NORMAL )  
  5.  .threadsToLoadObjects( 5 )  
  6.  .threadsForIndexWriter( 3 )  
  7.  .threadsForSubsequentFetching( 20 )  
  8.  .progressMonitor( monitor ) //a MassIndexerProgressMonitor implementation  
  9.  .startAndWait();  

 

 

这将会重建所有的User实例(和其子类实例),使用每次查询25个对象批量处理方式,创建5个并行线程加载用户实例;这些加载的User实例是管道至20并行线程来延迟加载用户中的集合。最后,3个并行线程用于analyze文本和写入index。

 

推荐CacheMode为CacheMode.IGNORE(默认),在大多数reindexing情景,缓存是没什么作用的;你可以激活其他的CacheMode,不过这依赖于你使用的数据。如果主实体与enum-like数据相关,它或许可以提高性能。

 

Note:MassIndexer是为了提高建立索引速度而产生的,它不需要事务处理。因为它是非事务的,所以它不推荐在MassIndexer运行期间让用户执行应用。

 

其他一些影响indexing time和内存消耗:

 

  • hibernate.search.[default|<indexname>].exclusive_index_use
  • hibernate.search.[default|<indexname>].indexwriter.batch.max_buffered_docs
  • hibernate.search.[default|<indexname>].indexwriter.batch.max_merge_docs
  • hibernate.search.[default|<indexname>].indexwriter.batch.merge_factor
  • hibernate.search.[default|<indexname>].indexwriter.batch.ram_buffer_size
  • hibernate.search.[default|<indexname>].indexwriter.batch.term_index_interval
  • hibernate.search.batchbackend.concurrent_writers
之前的版本中有一个max_field_length参数,但它已经被Lucene移除,使用LimitTokenCountAnalyzer可以获得相似的效果。
 
所有.indexwriter参数是Lucene指定的,Hibernate Search只是传递这些参数。详细请看Section 3.10, “Tuning Lucene indexing performance”
 
hibernate.search.batchbackend.concurrent_writers默认是2,它表示Analysis和 MassIndexing的indexWriter管道使用的线程数。MassIndexer.threadsForIndexWriter(int)覆 盖这个值。
原文:http://sin90lzc.iteye.com/blog/1112587

你可能感兴趣的:(Hibernate)