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
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
如果您想要为类型或者所有索引类型添加所有实例,推荐的方法是使用 MassIndexer:请参阅 以了解更多详细信息。
使用 MassIndexer 添加类型(或所有索引类型)的所有实例。如需更多信息 ,请参阅使用 MassIndexer。
7.6.2. 从索引中删除实例 复制链接链接已复制到粘贴板!
可以从 Lucene 索引中删除给定类型的实体或所有实体,而无需将它们从数据库中物理删除。此操作名为清除,也通过 FullTextSession 进行
。
清除操作允许从 Lucene 索引中删除单个实体或指定类型的所有实体,而无需将它们从数据库中物理删除。此操作使用 FullTextSession 来执行。
示例:从索引中清除实体的特定实例
建议在此类操作后优化索引。
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()索引重建
Hibernate.search.default.worker.batch_size
已被弃用,现在它提供了更好的控制
尝试使用批处理大小来确保您的应用不会超出内存:随着批处理大小的对象更快从数据库获取,但需要更多内存。
7.6.3.2. 使用 MassIndexer 复制链接链接已复制到粘贴板!
Hibernate Search 的 MassIndexer 使用多个并行线程重建索引。您可以选择选择需要重新加载哪些实体或重新索引所有实体。这种方法针对最佳性能进行了优化,但需要将应用程序设置为维护模式。当 MassIndexer 忙碌时,不建议查询索引。
示例:使用 MassIndexer 重新构建索引
fullTextSession.createIndexer().startAndWait();
fullTextSession.createIndexer().startAndWait();
这将重建索引,将其删除,然后从数据库重新加载所有实体。虽然使用起来简单,但建议进行一些调整以加快流程。
在 MassIndexer 过程中,索引的内容没有定义。如果在 MassIndexer 工作时执行查询,则很可能缺少某些结果。
示例:使用 Tuned MassIndexer
这将重新构建所有用户实例的索引(及子类型),并将创建 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
。