您好StackOverflow用户,
我遇到了这个问题 我有三个QueryOvers,每个QueryOvers返回一个候选ID列表,然后我用它来带来这些候选者。 为此我写了下面的代码。
private IQueryOver<CandidateEntity, CandidateEntity> UnionPublicWithPrivateCandidates(
IQueryOver<CandidateEntity, CandidateEntity> publicCandidates,
IQueryOver<CandidateEntity, CandidateEntity> privateCandidate,
IQueryOver<CandidateEntity, CandidateEntity> candidatesByUserRole)
{
return ActiveCandidatesQueryOver.Where(Restrictions.Disjunction()
.Add(Subqueries
.WhereProperty<CandidateEntity>(c => c.Id)
.In((QueryOver<CandidateEntity>)publicCandidates.Select(c => c.Id)))
.Add(Subqueries
.WhereProperty<CandidateEntity>(c => c.Id)
.In((QueryOver<CandidateEntity>)privateCandidate.Select(c => c.Id)))
.Add(Subqueries
.WhereProperty<CandidateEntity>(c => c.Id)
.In((QueryOver<CandidateEntity>)candidatesByUserRole.Select(c => c.Id))));
}
返回正确的结果,生成的查询如下所示
SELECT *
FROM Applicants
WHERE IsActive = 1
and (Id in (SELECT Id from **FirstQueryOver**)
**or** Id in (SELECT Id from **SecondQueryOver**)
**or** Id in (SELECT Id from **ThirdQueryOver**))
问题是它使用'或'。因此,查询速度非常缓慢。
如果我写这个:
SELECT *
FROM Applicants
WHERE IsActive = 1
and (Id in (SELECT Id from **FirstQueryOver**
union SELECT Id from **SecondQueryOver**
union SELECT Id from **ThirdQueryOver**))
它几乎立即完成。
您是否知道如何重构代码以获得更好的性能?
谢谢你, 阿德里安。
答案 0 :(得分:1)
我搜索但没有找到任何东西,所以我做了以下黑客攻击:
private IQueryOver<CandidateEntity, CandidateEntity> UnionPublicWithPrivateCandidates(
IQueryOver<CandidateEntity, CandidateEntity> publicCandidates,
IQueryOver<CandidateEntity, CandidateEntity> privateCandidate,
IQueryOver<CandidateEntity, CandidateEntity> candidatesByUserRole)
{
var excludedQueryCandidates = QueryOver
.WithSubquery.WhereNotExists(((QueryOver<CandidateEntity>)publicCandidates.Select(x => x.Id)))
.WithSubquery.WhereNotExists((QueryOver<CandidateEntity>)privateCandidate.Select(x => x.Id))
.WithSubquery.WhereNotExists((QueryOver<CandidateEntity>)candidatesByUserRole.Select(x => x.Id));
return QueryOver.WithSubquery.WhereNotExists((QueryOver<CandidateEntity>) excludedQueryCandidates.Select(Projections.Distinct(Projections.Id())));
}
这不是最佳解决方案,但应该有效。
答案 1 :(得分:0)
我不能说为什么联盟或联盟有这样的差异。 sql探查器,查询分析器和估计的执行计划应该让你更深入地了解sql运行查询的内容,我猜它在第一种情况下没有使用正确的索引。但是,我会尝试将您的查询重写为:
SELECT *
FROM Applicants
WHERE IsActive = 1
and (this_.Id in (SELECT this_0_.Id from **FirstQueryOver**
or **SecondQueryOver**
or **ThirdQueryOver**))
然后看看你有什么表现。