7.6. 手动索引更改


当 Hibernate Core 对数据库应用更改时,Hibernate Search 会检测到这些更改并自动更新索引(除非禁用了 EventListeners)。有时会在不使用 Hibernate 的情况下对数据库进行更改,因为备份恢复或者您的数据会受到影响。在这些情况下,Hibernate Search 会公开 Manual Index API 来显式更新或删除索引中的单个实体,重建整个数据库的索引,或删除对特定类型的所有引用。

所有这些方法仅影响 Lucene index,不会对数据库应用任何更改。

7.6.1. 将实例添加到索引

使用 FullTextSession.index(T 实体),您可以直接添加或更新特定对象实例到索引。如果此实体已经索引,则会更新索引。对索引的更改仅在事务提交时应用。

使用 FullTextSession.index(T 实体) 直接将对象或实例添加到索引中。索引会在实体索引时更新。Infinispan Query 在事务提交过程中对索引应用更改。

示例:使用 FullTextSession.index(T 实体)来索引实体.

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
Copy to Clipboard Toggle word wrap

如果您想要为类型或者所有索引类型添加所有实例,推荐的方法是使用 MassIndexer:请参阅 以了解更多详细信息。

使用 MassIndexer 添加类型(或所有索引类型)的所有实例。如需更多信息 ,请参阅使用 MassIndexer

7.6.2. 从索引中删除实例

可以从 Lucene 索引中删除给定类型的实体或所有实体,而无需将它们从数据库中物理删除。此操作名为清除,也通过 FullTextSession 进行

清除操作允许从 Lucene 索引中删除单个实体或指定类型的所有实体,而无需将它们从数据库中物理删除。此操作使用 FullTextSession 来执行。

示例:从索引中清除实体的特定实例

FullTextSession fullTextSession = Search.getFullTextSession(session);
Transaction tx = fullTextSession.beginTransaction();
for (Customer customer : customers) {
fullTextSession.purgeAll( Customer.class );
//optionally optimize the index
//fullTextSession.getSearchFactory().optimize( Customer.class );
tx.commit(); //index is updated at commit time
Copy to Clipboard Toggle word wrap

建议在此类操作后优化索引。

注意

FullTextEntityManager 上也提供方法索引、清除和清除All。

注意

所有手动索引方法(index、purge 和 purgeAll)都只会影响索引,而不是数据库,但是在事务成功提交或您使用 flushToIndexes 之前不会应用它们。

7.6.3. 重新构建索引

如果您更改了实体映射到索引,则有可能需要更新整个索引;例如,如果您决定使用其他分析器索引现有字段,您需要重新构建受影响类型的索引。另外,如果数据库被替换(例如从备份中恢复,从传统系统导入),您将希望能够从现有数据重建索引。Hibernate Search 提供两种主要策略:

在索引器中更改实体映射可能需要更新整个索引。例如,如果要使用其他分析器索引现有字段,则需要为受影响的类型重新构建索引。

此外,如果数据库被从备份中恢复或从传统系统导入,则需要从现有数据重新构建索引。Infinispan Query 提供两个主要策略:

  • 定期使用 FullTextSession.flushToIndexes(),同时在所有实体 上使用 FullTextSession.index( )。
  • 使用 MassIndexer

7.6.3.1. Using flushToIndexes()

此策略包括删除现有索引,然后使用 FullTextSession.purgeAll()和 FullTextSession.index() 将所有实体重新添加到索引中,但有一些内存和效率限制。为最大程度提高效率 Hibernate 搜索批处理索引操作,并在提交时执行它们。如果您希望为大量数据编制索引,您需要小心谨慎,因为所有文档都会保留在队列中,直到事务提交为止。如果您不定期清空队列,则可能会出现 OutOfMemoryException; 要使用 fullTextSession.flushToIndexes( )。每次 调用 fullTextSession.flushToIndexes( )(或者提交事务时),都会处理批处理队列,并应用所有索引更改。请注意,一旦刷新,更改就无法回滚。

示例:使用 index()和 flushToIndexes()索引重建

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();
Copy to Clipboard Toggle word wrap

注意

Hibernate.search.default.worker.batch_size 已被弃用,现在它提供了更好的控制

尝试使用批处理大小来确保您的应用不会超出内存:随着批处理大小的对象更快从数据库获取,但需要更多内存。

7.6.3.2. 使用 MassIndexer

Hibernate Search 的 MassIndexer 使用多个并行线程重建索引。您可以选择选择需要重新加载哪些实体或重新索引所有实体。这种方法针对最佳性能进行了优化,但需要将应用程序设置为维护模式。当 MassIndexer 忙碌时,不建议查询索引。

示例:使用 MassIndexer 重新构建索引

fullTextSession.createIndexer().startAndWait();
Copy to Clipboard Toggle word wrap

这将重建索引,将其删除,然后从数据库重新加载所有实体。虽然使用起来简单,但建议进行一些调整以加快流程。

警告

在 MassIndexer 过程中,索引的内容没有定义。如果在 MassIndexer 工作时执行查询,则很可能缺少某些结果。

示例:使用 Tuned MassIndexer

fullTextSession
 .createIndexer( User.class )
 .batchSizeToLoadObjects( 25 )
 .cacheMode( CacheMode.NORMAL )
 .threadsToLoadObjects( 12 )
 .idFetchSize( 150 )
 .progressMonitor( monitor ) //a MassIndexerProgressMonitor implementation
 .startAndWait();
Copy to Clipboard Toggle word wrap

这将重新构建所有用户实例的索引(及子类型),并将创建 12 个并行线程,以在每个查询使用 25 个对象的批处理来加载用户实例。这些相同的 12 个线程还需要处理索引化的嵌入式关系和自定义 FieldBridges 或 ClassBridges,以输出 Lucene 文档。在转换过程中,线程会触发额外属性加载。因此,需要大量并行工作线程。用于实际索引写入的线程数量由每个索引的后端配置定义。

建议将 cacheMode 保留至 CacheMode.IGNORE (默认值),因为在大多数重新索引的情况下,缓存会成为无用的额外开销。根据您的数据启用一些其他缓存模型 可能会很有用,因为如果主实体与索引中包含的类似数字数据相关,可能会提高性能。

注意

实现最佳性能的线程数量理想取决于您的整体架构、数据库设计和数据值。所有内部线程组都有有意义的名称,因此能够使用大多数诊断工具(包括线程转储)轻松识别它们。

注意

MassIndexer 不知道事务,因此无需再开始一项交易或提交。由于它不是事务性的,因此不建议允许用户在处理过程中使用系统,因为它不太可能找到结果,系统负载也可能太高。

其他影响索引时间和内存消耗的参数有:

  • hibernate.search.[default|<indexname>].exclusive_index_use
  • hibernate.search.[default|<indexname>].indexwriter.max_buffered_docs
  • hibernate.search.[default|<indexname>].indexwriter.max_merge_docs
  • hibernate.search.[default|<indexname>].indexwriter.merge_factor
  • hibernate.search.[default|<indexname>].indexwriter.merge_min_size
  • hibernate.search.[default|<indexname>].indexwriter.merge_max_size
  • hibernate.search.[default|<indexname>].indexwriter.merge_max_optimize_size
  • hibernate.search.[default|<indexname>].indexwriter.merge_calibrate_by_deletes
  • hibernate.search.[default|<indexname>].indexwriter.ram_buffer_size
  • hibernate.search.[default|<indexname>].indexwriter.term_index_interval

之前的版本也具有 max_field_length,但这已从 Lucene 中删除。通过使用 LimitTokenCountAnalyzer 可以获得类似的效果。

all .indexwriter 参数是特定于 Lucene 的,Hibernate 搜索通过这些参数.

MassIndexer 使用正向结果仅滚动到要加载的主键,但 MySQL 的 JDBC 驱动程序会加载内存中的所有值。为了避免这个"优化"将 idFetchSize 设置为 Integer.MIN_VALUE

返回顶部
Red Hat logoGithubredditYoutubeTwitter

学习

尝试、购买和销售

社区

关于红帽文档

通过我们的产品和服务,以及可以信赖的内容,帮助红帽用户创新并实现他们的目标。 了解我们当前的更新.

让开源更具包容性

红帽致力于替换我们的代码、文档和 Web 属性中存在问题的语言。欲了解更多详情,请参阅红帽博客.

關於紅帽

我们提供强化的解决方案,使企业能够更轻松地跨平台和环境(从核心数据中心到网络边缘)工作。

Theme

© 2025 Red Hat