Lucene TwoWayFieldBridge 慢查询
Lucene TwoWayFieldBridge slow query
我在 lucene 中构建了一个查询以替换 SQL 查询,但得出的结论是 lucene 查询慢了多个数量级。我的意思是较慢,从 250 毫秒到 5000 毫秒,所以 unacceptable。设置有点特殊,估计是哪里出了问题。
被索引和搜索的主要字段是 Map<String, String>
类型,映射为:
@ElementCollection(targetClass = String.class)
@CollectionTable(name = "data")
private Map<String, String> data;
或者换句话说,这个实体有一个关联的 table 键值对。我们想要搜索这些值,但仅限于特定的键。因此,如果我们遇到满足我们需要的密钥,我的 fieldbridge 实现将在文档中创建一个条目。 (我们显然不想存储索引中的每个键。)
主查询其实没什么特别的:
FullTextSession fullTextSession = Search.getFullTextSession(getCurrentSession());
try {
fullTextSession.createIndexer(Form.class).startAndWait();
} catch (InterruptedException ex) {
LOG.error("Exception when indexing: ", ex);
}
QueryBuilder builder = fullTextSession.getSearchFactory().buildQueryBuilder().forEntity(Entity.class).get();
org.apache.lucene.search.Query query;
BooleanJunction booleanJunction = builder.bool();
booleanJunction.must(builder.keyword().onFields("data")
.matching(searchString).createQuery());
因此,我的问题是,我做错了什么以至于这个查询需要这么长时间才能处理?如果您希望我提供任何可能有助于您解决此问题的额外信息,请询问,我会提供。我不知道包含 TwoWayFieldBridge
代码有多重要,但如果问题出在那里,一定要问。
更新:
公认的答案是正确的,因为这导致了显着的放缓。我建议您的应用程序从一开始就被索引,如果这不可能,您可以附加一种启动监听器(取决于所使用的框架或上下文),并使用此代码启动索引器。请注意,您需要打开足够的可用连接,否则这可能会阻止您的应用程序启动。
如果您显示的代码 "search code",那么您的问题是,您在每次搜索时都为数据编制索引。这索引 Form
class:
try {
fullTextSession.createIndexer(Form.class).startAndWait();
} catch (InterruptedException ex) {
LOG.error("Exception when indexing: ", ex);
}
您只想执行一次,或者在数据更改时执行此操作。您的代码使用质量索引器 API 来索引现有数据 (createIndexer(Form.class).startAndWait()
)。此方法的目的是创建现有数据的初始索引。一旦数据被索引,您就可以依赖 Hibernate Search 的自动索引,它会为数据更改注册一个监听器,并且只对添加或更改的数据进行索引。或者你可以手动索引,如果你want/need这个级别的控制。我建议您参阅文档以了解有关这些不同类型索引的更多信息。
我在 lucene 中构建了一个查询以替换 SQL 查询,但得出的结论是 lucene 查询慢了多个数量级。我的意思是较慢,从 250 毫秒到 5000 毫秒,所以 unacceptable。设置有点特殊,估计是哪里出了问题。
被索引和搜索的主要字段是 Map<String, String>
类型,映射为:
@ElementCollection(targetClass = String.class)
@CollectionTable(name = "data")
private Map<String, String> data;
或者换句话说,这个实体有一个关联的 table 键值对。我们想要搜索这些值,但仅限于特定的键。因此,如果我们遇到满足我们需要的密钥,我的 fieldbridge 实现将在文档中创建一个条目。 (我们显然不想存储索引中的每个键。)
主查询其实没什么特别的:
FullTextSession fullTextSession = Search.getFullTextSession(getCurrentSession());
try {
fullTextSession.createIndexer(Form.class).startAndWait();
} catch (InterruptedException ex) {
LOG.error("Exception when indexing: ", ex);
}
QueryBuilder builder = fullTextSession.getSearchFactory().buildQueryBuilder().forEntity(Entity.class).get();
org.apache.lucene.search.Query query;
BooleanJunction booleanJunction = builder.bool();
booleanJunction.must(builder.keyword().onFields("data")
.matching(searchString).createQuery());
因此,我的问题是,我做错了什么以至于这个查询需要这么长时间才能处理?如果您希望我提供任何可能有助于您解决此问题的额外信息,请询问,我会提供。我不知道包含 TwoWayFieldBridge
代码有多重要,但如果问题出在那里,一定要问。
更新: 公认的答案是正确的,因为这导致了显着的放缓。我建议您的应用程序从一开始就被索引,如果这不可能,您可以附加一种启动监听器(取决于所使用的框架或上下文),并使用此代码启动索引器。请注意,您需要打开足够的可用连接,否则这可能会阻止您的应用程序启动。
如果您显示的代码 "search code",那么您的问题是,您在每次搜索时都为数据编制索引。这索引 Form
class:
try {
fullTextSession.createIndexer(Form.class).startAndWait();
} catch (InterruptedException ex) {
LOG.error("Exception when indexing: ", ex);
}
您只想执行一次,或者在数据更改时执行此操作。您的代码使用质量索引器 API 来索引现有数据 (createIndexer(Form.class).startAndWait()
)。此方法的目的是创建现有数据的初始索引。一旦数据被索引,您就可以依赖 Hibernate Search 的自动索引,它会为数据更改注册一个监听器,并且只对添加或更改的数据进行索引。或者你可以手动索引,如果你want/need这个级别的控制。我建议您参阅文档以了解有关这些不同类型索引的更多信息。