首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 软件管理 > 软件架构设计 >

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

2012-09-08 
Hibernate Search(基于version3.4)--第六章Manual index changesManual index changes?当Hibernate core应

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)

?

FullTextSession fullTextSession = Search.getFullTextSession(session);Transaction tx = fullTextSession.beginTransaction();Object customer = fullTextSession.load( Customer.class, 8 );fullTextSession.index(customer);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

?

FullTextSession fullTextSession = Search.getFullTextSession(session);Transaction tx = fullTextSession.beginTransaction();for (Customer customer : customers) {    fullTextSession.purge( Customer.class, customer.getId() );}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

?

FullTextSession fullTextSession = Search.getFullTextSession(session);Transaction tx = fullTextSession.beginTransaction();fullTextSession.purgeAll( Customer.class );//optionally optimize the index//fullTextSession.getSearchFactory().optimize( Customer.class );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()

?

fullTextSession.setFlushMode(FlushMode.MANUAL);fullTextSession.setCacheMode(CacheMode.IGNORE);transaction = fullTextSession.beginTransaction();//Scrollable results will avoid loading too many objects in memoryScrollableResults 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();
?

?

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

?

fullTextSession.createIndexer().startAndWait();

?

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

?

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

?

Example 6.6. Using a tuned MassIndexer

?

fullTextSession .createIndexer( User.class ) .batchSizeToLoadObjects( 25 ) .cacheMode( CacheMode.NORMAL ) .threadsToLoadObjects( 5 ) .threadsForIndexWriter( 3 ) .threadsForSubsequentFetching( 20 ) .progressMonitor( monitor ) //a MassIndexerProgressMonitor implementation .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_usehibernate.search.[default|<indexname>].indexwriter.batch.max_buffered_docshibernate.search.[default|<indexname>].indexwriter.batch.max_merge_docshibernate.search.[default|<indexname>].indexwriter.batch.merge_factorhibernate.search.[default|<indexname>].indexwriter.batch.ram_buffer_sizehibernate.search.[default|<indexname>].indexwriter.batch.term_index_intervalhibernate.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)覆盖这个值。

?

?

?

?

?

热点排行