6

こんにちはStackOverflowユーザー、

私はこの問題に遭遇しました。3つのQueryOverがあり、それぞれが候補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**))

ほぼ瞬時に終了します。

パフォーマンスを向上させるためにコードをリファクタリングする方法について何か考えがありますか?

ありがとう、エイドリアン。

4

2 に答える 2

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())));
}

これは最善の解決策ではありませんが、機能するはずです。

于 2013-05-14T14:03:09.157 に答える
0

なぜor対組合がそのような違いを持っ​​ているのか私には言えません。SQLプロファイラー、クエリアナライザー、および推定実行プランにより、SQLがクエリを実行するために何を行うかについて、より多くの洞察が得られるはずです。最初のケースでは、適切なインデックスを使用していないと思います。ただし、クエリを次のように書き直そうとします。

SELECT *
  FROM   Applicants  
  WHERE  IsActive = 1
    and (this_.Id in (SELECT this_0_.Id from **FirstQueryOver** 
                                          or **SecondQueryOver** 
                                          or **ThirdQueryOver**))

そして、あなたがその時どのようなパフォーマンスを持っているかを見てください。

于 2012-10-03T11:39:41.813 に答える