我有一个代表一篇文章的模型:
public class Article {
@Id
private Integer id;
private String title;
private String content;
// ...
// plenty of other article properties, used to classify and filter over them
// ...
@ElementCollection
private Set<String> tags;
}
以及其他人用来动态构建查询的规范:
...
public static Specification<Article> byTagAnyOf(Set<String> referenceTags) {
return ((root, query, builder) -> {
if (CollectionUtils.isEmpty(referenceTags)) {
return builder.conjunction();
}
return builder.or(referenceTags.stream()
.map(tag -> builder.isMember(tag, root.get("tags")))
.toArray(Predicate[]::new));
});
}
...
这个解决方案实际上有效,但是创建了一个包含大量
or
语句的查询,执行 tag
元素的选择,这会导致性能问题。
有没有办法通过加入
referenceTags
或通过规范 API 选择 except 来执行数组相交检查?
由于性能问题,您可能有多种原因,对我来说调查所有这些原因都是有意义的。
关于你的问题,你有很多 OR 条件,因为是你用
builder.or
指定了这个。
老实说,我不明白你的数组交集是什么意思,但我有一个问题要问你:你是否考虑使用 IN 语句而不是所有可能标签的 OR ?
我建议您检查的第二件事是生成的查询,请验证数据库中触发的查询是什么(如果激活它,您可以在日志中找到它),至少对我来说事情会更清楚。
我完全理解您正在使用规范动态生成查询,这没有任何问题,但是您确实正在生成“不可预测”的查询,这将迫使您在数据库中创建所有可能的索引组合(这是疯狂地为所有可能的组合生成索引)。
OR 子句链可能会阻止数据库使用正确的索引,请尝试使用 IN 语句并让我知道。
总而言之,我的建议是: