2012-10-03 15 views
6

Merhaba StackOverflow kullanıcılarınınNHibernate - Ben bu sorunu koştu Birliği üç QueryOvers

Üç QueryOvers var ve bunların her Sonra bu adayları getirmek için kullandıkları aday kimliklerinin bir listesini döndürür. Bunun için aşağıdaki kodu yazdım.

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

Bu, doğru sonuçlar verir ve bu

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**)) 

sorun kullandığı 'veya' olmasıdır gibi oluşturulan sorgu görünüyor. Bundan dolayı sorgu ağrılı bir şekilde yavaştır.

SELECT * 
FROM Applicants 
WHERE IsActive = 1 
    and (Id in (SELECT Id from **FirstQueryOver** 
        union SELECT Id from **SecondQueryOver** 
        union SELECT Id from **ThirdQueryOver**)) 

Neredeyse anında bitirir:

yerine ben yazıyorum.

Daha iyi performans için kodu nasıl yeniden gözden geçirmem gerektiğiyle ilgili bir fikriniz var mı?

Teşekkür ederiz, Adrian.

+0

bir bellek içi Birliği bir seçenek mi yapıyor? –

+0

@Andrew Whitaker Sadece bunu yapmayı bitirdim ama gerçekten hoşlanmıyorum çünkü birden fazla sorgu tarafından döndürülen kayıtlar var, bu yüzden çiftleri el ile ortadan kaldırmak zorundayım. –

cevap

0

Sendikanın neden ya da neden böyle bir farklılığa sahip olduğunu söyleyemem. Sql profiler, sorgu analizcisi ve tahmini yürütme planı size sorguyu çalıştırmak için sql ne yaptığını daha fazla bilgi vermelidir, sanırım ilk durumda doğru indeksi kullanmıyor.

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

ve daha sonra ne preformance bkz: Ancak sorgunuzu yeniden yazmak için çalışacaktı. En iyi çözüm yolu değil, ama çalışması gerekir

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

:

Aradım ama bir şey bulamadık
+0

Merhaba eş, yardımlarınız için teşekkürler. Sütunlarımdaki dizinleri kontrol edeceğim. Ancak, C# kodunu yeniden kodlamada bana ipuçları verebilirseniz çok memnun olurum. –